c++++中构造函数分为默认构造、参数化构造、拷贝构造和移动构造四种类型,分别用于无参初始化、自定义初始化、复制对象和高效转移资源;默认构造函数在未定义其他构造函数时由编译器自动生成,参数化构造需手动定义以实现特定初始化,拷贝构造以const引用为参数用于复制对象,移动构造以右值引用为参数通过转移资源提升性能,且应标记noexcept以支持stl优化,若定义了析构函数或拷贝操作则需遵循rule of three/five手动管理资源,合理使用= default可强制生成默认构造,= delete可禁用拷贝构造,而现代编译器可能通过rvo/nrvo优化省略拷贝或移动过程,掌握这些构造函数的区别与使用场景是c++对象生命周期管理的基础。

在C++中,构造函数是用于初始化对象的特殊成员函数。根据用途和参数的不同,构造函数可以分为几种类型。下面详细介绍常见的构造函数类型,并对比默认构造、参数化构造、拷贝构造和移动构造。
一、构造函数的类型
-
默认构造函数(Default Constructor)
- 没有参数,或所有参数都有默认值。
- 编译器在没有用户定义构造函数时会自动生成一个。
- 用于创建对象时不传参数的情况。
class MyClass { public: MyClass() { /* 初始化 */ } }; -
参数化构造函数(Parameterized Constructor)
- 接收一个或多个参数,用于自定义初始化。
- 常用于设置对象的初始状态。
class MyClass { public: MyClass(int a, int b) : x(a), y(b) {} private: int x, y; }; -
拷贝构造函数(Copy Constructor)
- 以同类型对象的引用为参数,用于创建新对象并复制原对象的值。
- 形参通常是
const T&
。 - 在值传递、返回局部对象、初始化新对象时被调用。
class MyClass { public: MyClass(const MyClass& other) { x = other.x; y = other.y; } }; -
移动构造函数(Move Constructor)
- 接收一个右值引用(
T&&
),将资源“移动”而非复制。 - 提高性能,避免不必要的深拷贝。
- 适用于临时对象或
std::move()
的场景。
class MyClass { public: MyClass(MyClass&& other) noexcept { x = other.x; y = other.y; other.x = 0; other.y = 0; // 原对象资源被“掏空” } }; - 接收一个右值引用(
二、四种构造函数的对比
| 构造函数类型 | 调用时机 | 参数形式 | 是否自动生成 | 典型用途 |
|---|---|---|---|---|
| 默认构造函数 | @@######@@ | 无参数或全默认值 | 是(若未定义其他构造) | 创建未初始化或默认状态对象 |
| 参数化构造函数 | @@######@@ | 带参数 | 否(需手动定义) | 定制初始化对象 |
| 拷贝构造函数 | @@######@@ @@######@@ |
@@######@@ | 是(若未定义) | 复制已有对象 |
| 移动构造函数 | @@######@@ @@######@@ |
@@######@@ | 是(若未定义且无自定义拷贝/赋值) | 高效转移资源 |
三、关键区别与注意事项
-
默认构造函数不一定“什么都不做”,它可能初始化成员为默认值。如果类中定义了其他构造函数,编译器不会自动生成默认构造函数,除非显式声明
MyClass obj;
。MyClass obj(1, 2);
-
拷贝构造 vs 移动构造:
- 拷贝:安全但可能慢(尤其是深拷贝)。
- 移动:高效,但原对象进入“有效但未定义”状态(通常被置空)。
- 移动构造应标记
MyClass obj2 = obj1;
,否则某些STL操作可能不使用它。
-
隐式调用与显式禁止:
- 可以用
func(obj);
防止参数化构造函数被隐式调用。 - 不需要拷贝语义的类(如独占资源)应删除拷贝构造:
const T&
- 可以用
-
编译器自动生成规则(Rule of Three / Rule of Five):
- 如果你定义了析构函数、拷贝构造、拷贝赋值中的任意一个,通常需要手动定义其余。
- C++11后扩展为 Rule of Five,包括移动构造和移动赋值。
四、示例场景对比
MyClass obj3 = std::move(obj1);
注意:现代编译器常进行 返回值优化(RVO/NRVO),可能直接构造对象,跳过拷贝或移动。
基本上就这些。理解这四种构造函数的使用场景和区别,是掌握C++对象生命周期管理的基础。尤其在涉及资源管理(如指针、文件句柄)时,合理定义拷贝和移动语义至关重要。
return临时对象;
T&&
= default
MyClass() = default; // 强制生成默认构造
noexcept
explicit
MyClass(const MyClass&) = delete;
MyClass a; // 调用默认构造 MyClass b(1, 2); // 调用参数化构造 MyClass c = b; // 调用拷贝构造 MyClass d = std::move(b); // 调用移动构造 MyClass e = createTemp(); // 临时对象,通常调用移动构造(或RVO优化)










