C++ 构造函数
构造函数用于初始化对象的内存空间。语法如下:
ClassName(parameters) {
// 初始化代码
}
- 与类同名,无返回值。
- 可重载(多个不同参数的构造函数)。
- 默认构造函数无参数,若未显式定义,编译器会自动生成一个。
拷贝构造函数
拷贝构造函数用于通过已有对象创建新对象。语法如下:
ClassName(const ClassName& other) {
// 拷贝 other 的成员到当前对象
}
- 参数为常量引用(避免无限递归)。
- 默认拷贝构造函数逐成员复制(浅拷贝)。
- 常用于函数传参或返回对象时。
移动构造函数
移动构造函数用于“窃取”临时对象(右值)的资源。语法如下:
ClassName(ClassName&& other) noexcept {
// 将 other 的资源转移到当前对象
// 将 other 置为有效但未指定的状态
}
- 参数为右值引用(
&&
)。 - 标记为
noexcept
以兼容标准库容器。 - 避免深拷贝,提升性能(如转移指针所有权)。
移动赋值函数
移动赋值函数用于将右值对象的资源赋给已存在的对象。语法如下:
ClassName& operator=(ClassName&& other) noexcept {
if (this != &other) {
// 释放当前对象资源
// 转移 other 的资源
}
return *this;
}
- 需检查自赋值(
this != &other
)。 - 返回当前对象的引用以支持链式赋值。
委托构造函数
委托构造函数允许一个构造函数调用同类其他构造函数。语法如下:
ClassName() : ClassName(default_arg) { } // 委托到另一个构造函数
- 初始化列表中调用,防止重复代码。
- 不能形成循环委托。
析构函数
析构函数用于释放对象占用的资源。语法如下:
~ClassName() {
// 清理代码(如释放动态内存)
}
- 无参数,无返回值,不可重载。
- 若未显式定义,编译器生成默认析构函数。
区别与记忆技巧
-
构造函数 vs 析构函数
- 构造函数名与类同名,析构函数名前加 ~。
- 构造函数初始化对象,析构函数清理资源。
-
拷贝 vs 移动
- 拷贝操作保留原对象(参数为
const&
),移动操作“窃取”资源(参数为&&
)。 - 移动语义用于临时对象(右值),提升效率。
- 拷贝操作保留原对象(参数为
-
移动构造 vs 移动赋值
- 移动构造函数初始化新对象,移动赋值函数覆盖已存在对象。
-
委托构造函数
- 仅用于构造函数间的代码复用,减少冗余。
记忆口诀:
- 构造初始化,析构清资源。
- 拷贝保原样,移动抢资源。
- 移动构造新对象,移动赋值旧换新。
- 委托调兄弟,代码不重复。
代码示例
class Example {
public:
int* data;
// 构造函数
Example(int val) : data(new int(val)) {}
// 拷贝构造函数
Example(const Example& other) : data(new int(*other.data)) {}
// 移动构造函数
Example(Example&& other) noexcept : data(other.data) {
other.data = nullptr;
}
// 移动赋值函数
Example& operator=(Example&& other) noexcept {
if (this != &other) {
delete data; // 释放原有资源
data = other.data; // 窃取资源
other.data = nullptr;
}
return *this;
}
// 委托构造函数
Example() : Example(0) {} // 委托给带参数的构造函数
// 析构函数
~Example() { delete data; }
};