存在析构函数或拷贝赋值运算符时,不应缺少拷贝构造函数
5.1.6 ID_missingCopyConstructor
三个紧密相关的函数:
- 拷贝构造函数
- 拷贝赋值运算符
- 析构函数
当这三个函数中的任何一个函数被定义时,说明对象在资源管理等方面有特定的需求,其他两个函数也需要被定义,否则难以适应各种应用场景,易产生意料之外的错误,这种规则称为“Rule of three”。
如果缺少某个函数,编译器会生成相关默认函数,但其特定需求不会被实现。
示例:
class A // Non-compliant
{
int* p = new int[8];
public:
~A() {
delete[] p;
}
}; // Missing copy constructor and assignment operator
void foo()
{
A a;
A b(a); // Shallow copy
....
} // Double free
void bar(A& a, A& b)
{
a = b; // Memory leak
}
例中的类有析构函数,但没有拷贝构造函数和拷贝赋值运算符,只能进行变量值的复制,使多个对象的资源指针指向同一块内存区域,导致重复释放和内存泄漏,所以应定义拷贝构造函数和拷贝赋值运算符重新分配内存并复制数据。
同理,在遵循 C++11 及之后标准的代码中:
- 拷贝构造函数
- 拷贝赋值运算符
- 析构函数
- 移动构造函数
- 移动赋值运算符
当定义了这五个函数中的任何一个函数时,其他四个函数也需要定义,详见 ID_violateRuleOfFive。