特殊成员函数
编译器隐式声明规则
| 用户声明的成员函数 | 默认构造函数 | 析构函数 | 拷贝构造函数 | 拷贝赋值 | 移动构造函数 | 移动赋值 |
|---|---|---|---|---|---|---|
| 无声明 | 默认生成 | 默认生成 | 默认生成 | 默认生成 | 默认生成 | 默认生成 |
| 任何构造函数 | 不声明 | 默认生成 | 默认生成 | 默认生成 | 默认生成 | 默认生成 |
| 默认构造函数 | 用户声明 | 默认生成 | 默认生成 | 默认生成 | 默认生成 | 默认生成 |
| 析构函数 | 默认生成 | 用户声明 | 默认生成 | 默认生成 | 不声明 | 不声明 |
| 拷贝构造函数 | 不声明 | 默认生成 | 用户声明 | 默认生成 | 不声明 | 不声明 |
| 拷贝赋值 | 默认生成 | 默认生成 | 默认生成 | 用户声明 | 不声明 | 不声明 |
| 移动构造函数 | 不声明 | 默认生成 | 删除 | 删除 | 用户声明 | 不声明 |
| 移动赋值 | 默认生成 | 默认生成 | 删除 | 删除 | 不声明 | 用户声明 |
关键术语说明:
- 默认生成:编译器自动生成该成员函数。
- 用户声明:用户显式定义或标记为
default(如ClassName() = default;)。 - 不声明:编译器不会生成该成员函数(需手动定义,否则相关操作不可用)。
- 删除:编译器隐式删除该成员函数(如
operator=(const T&) = delete;)。
核心规则总结:
-
移动语义的隐式生成:
- 若用户声明了拷贝操作(拷贝构造/拷贝赋值)、析构函数或移动操作中的任意一个,编译器不会自动生成移动操作。
- 若未声明上述函数,且类支持移动语义(如无不可移动的成员),编译器会生成默认移动操作。
-
拷贝语义的隐式生成:
- 若用户声明了移动操作,编译器不会自动生成拷贝操作(需手动定义)。
-
析构函数的特殊影响:
- 若用户声明析构函数,编译器不会生成移动操作,但保留默认拷贝操作。
示例场景:
-
场景 1:用户未声明任何特殊成员函数
class A {}; // 编译器生成所有默认成员函数 -
场景 2:用户声明拷贝构造函数
class B { public: B(const B&) {} // 拷贝构造函数 }; // 编译器不会生成默认移动构造/移动赋值 -
场景 3:用户声明移动赋值
class C { public: C& operator=(C&&) { return *this; } // 移动赋值 }; // 编译器删除拷贝构造/拷贝赋值,需手动定义
该表格和规则是理解 C++ 类设计中特殊成员函数隐式生成逻辑的重要参考。
602

被折叠的 条评论
为什么被折叠?



