C++ 三法则
三法则是在C++中构建异常安全代码的经验法则之一。这些规则规定了类的默认成员应该如何用于免异常实践。
三法则也称为“三大法则”或“大三法则”,它规定,如果一个类定义了以下三个成员中的任何一个,那么它就应该显式地定义所有三个:
- 析构函数
- 复制构造函数
- 复制赋值运算符
这三个是类的特殊成员函数。如果程序员没有显式定义它们中的任何一个,编译器将提供隐式版本。如果显式定义了任何一个,则意味着其他两个的隐式版本可能不正确,必须重新定义。
发生这种情况是因为隐式生成的构造函数和赋值运算符对数据成员进行浅拷贝。当类包含指向动态分配资源的指针时,我们需要深拷贝。
默认析构函数删除未使用的对象。如果没有定义复制构造函数,则析构函数将运行两次,一次用于包含副本的对象,另一次用于从中复制数据成员的对象。为避免这种情况,需要显式定义。
让我们通过一个例子来理解,在这个例子中,没有复制构造函数和复制赋值运算符,但存在析构函数:
示例
#include <stdio.h> class Numbers{ private: int num; int* ptr; public: Numbers( int n, int* p ) //copy constructor{ num =n ; ptr = new int[ num ]; } ~Numbers() //destructor{ delete ptr; ptr = NULL; } }; int main(){ int arr[ 4 ] = { 11, 22, 33, 44 }; Numbers Num1( 4, arr ); // this creates problem Numbers Num2( Num1 ); return 0; }
输出
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001f46c20 *** Aborted
发生这种情况是因为当程序超出范围时,析构函数被调用了两次。首先删除 Num1,然后删除 Num2。默认复制构造函数创建指针 ptr 的副本,但没有为其分配内存。因此,当 Num1 被移除后,后续的 ptr 将导致程序崩溃。
广告