C++ 中由编译器默认生成的类方法
在类中,如果你未显示定义下列一些函数,编译器会帮你自动生成它们的默认版本。
📌 一、编译器默认生成的六大函数
| 函数名称 | 触发条件 | C++标准支持 |
|---|---|---|
| 默认构造函数 | 用户未定义任何构造函数时生成 | C++98 |
| 析构函数 | 用户未定义时自动生成 | C++98 |
| 复制构造函数 | 用户未定义时生成浅拷贝版本 | C++98 |
| 复制赋值运算符 | 用户未定义时生成浅拷贝版本 | C++98 |
| 移动构造函数 | 用户未定义拷贝控制成员时生成 | C++11 |
| 移动赋值运算符 | 用户未定义拷贝控制成员时生成 | C++11 |
🔍 二、各函数处理成员变量的机制
1. 默认构造函数
ClassName() = default;
- 内置类型:不初始化(保留内存原始值)[1]
- 类类型成员:递归调用其默认构造函数
- 继承体系:调用基类默认构造函数
2. 复制构造函数
ClassName(const ClassName& src)
: member1(src.member1),
member2(src.member2) {}
- 基本类型:直接拷贝值
- 类类型成员:调用其复制构造函数
- 指针成员:仅复制指针地址(浅拷贝)
3. 复制赋值运算符
ClassName& operator=(const ClassName& src) {
member1 = src.member1;
member2 = src.member2;
return *this;
}
- 基本类型:直接赋值
- 类类型成员:调用其赋值运算符
- 指针成员:仅复制指针(导致悬空指针)
4. 析构函数
~ClassName() {}
- 类类型成员:递归调用其析构函数
- 指针成员:不执行delete操作(内存泄漏风险)
5. 移动构造函数(C++11)
ClassName(ClassName&& src)
: member1(std::move(src.member1)),
member2(std::move(src.member2)) {}
- 基本类型:直接转移值
- 类类型成员:调用其移动构造函数
- 指针成员:转移所有权(源指针置空)
6. 移动赋值运算符(C++11)
ClassName& operator=(ClassName&& src) {
member1 = std::move(src.member1);
member2 = std::move(src.member2);
return *this;
}
⚠️ 三、关键风险与最佳实践
风险案例:浅拷贝陷阱
class String {
char* data; // 动态分配内存
public:
// 默认生成的复制构造函数会导致双重释放
};
必须自定义的场景:
- 类包含指针成员(需深拷贝)
- 类管理非POD类型资源(文件句柄等)
- 需要维护对象计数等特殊逻辑
三法则(Rule of Three):
- 如果定义了以下任一函数,通常需要同时定义:
- 析构函数
- 复制构造函数
- 复制赋值运算符
五法则(C++11扩展):
- 增加移动构造函数和移动赋值运算符的定制需求
📚 四、验证示例代码
#include <iostream>
using namespace std;
class Test {
int* ptr;
public:
Test() : ptr(new int(10)) {} // 默认构造
~Test() { delete ptr; } // 必须自定义析构
void show() const {
cout << "Value: " << *ptr << endl;
}
};
int main() {
Test a;
Test b = a; // 默认复制构造导致双重释放!
a.show();
return 0;
}
根据C++标准,内置类型在默认构造函数中不进行初始化 ↩︎

浙公网安备 33010602011771号