在建立例外安全代码的经验法则下,三规则是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 ); //这会产生问题 Numbers Num2( Num1 ); return 0; }
输出结果
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001f46c20 *** Aborted
发生这种情况的原因是,当程序超出范围时,析构函数将被调用两次。首先删除Num1,然后删除Num2。默认的复制构造函数创建指针ptr的副本,但未为其分配内存。因此,删除Num1后,随后的ptrs会导致程序崩溃。