C++8 默认函数和删除函数
文章目录
在 C++11 及后续标准中,默认函数和删除函数是控制类行为的核心机制,主要用于精确管理特殊成员函数的生成和禁用。以下是关键要点总结:
一、默认函数(=default
)
1 定义
编译器自动生成的 6 种特殊成员函数,包括:
- 默认构造函数
- 析构函数
- 拷贝构造函数
- 拷贝赋值运算符
- 移动构造函数(C++11 新增)
- 移动赋值运算符(C++11 新增)
2 核心特性
为什么要显式要求编译器生成默认函数,因为隐式生成有以下限制原因,所以要显式要求生成。
- 隐式生成条件:若未定义任何构造函数,编译器自动生成默认构造函数。
- 生成规则:定义某些函数可能影响其他函数的自动生成。例如:
- 声明移动构造函数会禁用拷贝操作的自动生成。
- 显式定义析构函数会禁用移动操作的生成。
3 应用场景
- 简化代码:避免手动编写空构造函数或拷贝逻辑。
- 优化性能:编译器生成的默认函数通常比手动实现更高效。
- 显式生成:通过
=default
显式要求编译器生成默认实现。
4 用法示例
class MyClass {
public:
int value = 0;
MyClass() = default; // 显式生成默认构造函数
// 显式生成移动构造函数和移动赋值运算符
MyClass(MyClass&&) = default;
MyClass& operator=(MyClass&&) = default[1]();
};
// 使用
MyClass a; // 调用默认构造函数
MyClass b = std::move(a); // 调用默认移动构造
MyClass c;
c = std::move(a); // 调用默认移动赋值
二、删除函数(=delete
)
1. 定义
通过 =delete
显式禁用特定函数,使其无法被调用。
2. 核心特性
-
禁用范围:
- 特殊成员函数(如拷贝构造、赋值运算符)
- 普通成员函数
- 非成员函数(如全局函数)
-
语法示例:
class NonCopyable { public: NonCopyable(const NonCopyable&) = delete; // 禁用拷贝构造 NonCopyable& operator=(const NonCopyable&) = delete; // 禁用拷贝赋值 };
3. 应用场景
-
防止拷贝:管理资源(如动态内存)时禁用拷贝操作,避免浅拷贝问题。
-
限制参数类型:阻止隐式类型转换。例如禁用
int
参数调用:void func(double) {} void func(int) = delete; // 禁止传入 int 类型
-
替代旧方法:取代 C++11 之前通过私有化拷贝函数(不实现)的繁琐操作。
4. 用法示例
1. 禁止拷贝操作
资源管理类(如文件句柄)禁用拷贝以防止浅拷贝问题:
class FileHandler {
public:
FileHandler(const char* path) { /* 打开文件 */ }
~FileHandler() { /* 关闭文件 */ }
// 禁用拷贝构造和拷贝赋值
FileHandler(const FileHandler&) = delete;
FileHandler& operator=(const FileHandler&) = delete;
};
// 错误用法
FileHandler f1("test.txt");
FileHandler f2 = f1; // 编译报错:拷贝构造函数被删除
2. 限制参数类型
阻止隐式类型转换导致非预期调用:
void ProcessData(double value) { /* ... */ }
void ProcessData(int) = delete; // 禁止传入 int 类型
// 错误用法
ProcessData(5); // 编译报错:int 版本被删除
3. 禁用默认构造函数
强制用户必须通过带参构造创建对象:
class Logger {
public:
Logger() = delete; // 禁止默认构造
Logger(const std::string& name) { /* ... */ }
};
// 正确用法
Logger log("system");
// Logger log2; // 编译报错:默认构造函数被删除
三、默认与删除函数的交互影响
- 隐式删除条件:
- 类成员无法默认构造/拷贝时,相关函数会被隐式删除。
- 若析构函数被删除或不可访问,拷贝构造函数和移动构造函数也会被删除。
- 移动语义控制:显式定义移动操作会禁用拷贝操作的自动生成,反之亦然。
四、实际开发建议
- 优先使用
=default
:简化代码并保持编译器优化能力。 - 资源管理类必用
=delete
:如智能指针、文件句柄等需显式禁用拷贝。 - 结合移动语义:在禁用拷贝时,显式定义移动操作提升效率。
通过合理使用默认和删除函数,开发者可以编写更安全、高效的 C++ 代码。