Rule of three

来源:互联网 发布:js 如何取list 编辑:程序博客网 时间:2024/05/17 07:17

在编写class时,有三个元素:

copy constructor

operator =

destructor

如果出现了其中一个,为了代码的健壮性和完整性,应该补上剩下两个元素,尤其是在我们需要deep copying的时候。

举个例子来说明养成这个习惯的意义:假设在class中有一个指向heap某区域的指针,我们在destructor中把它delete了,那么如果我们没有定义copy constructor和operator =,则编译器默认会给class加上一个shallow copy的copy constructor和operator =。这样一来如果先存在一个该class的实例a,然后我们通过=或者copy constructor定义了另一个实例b,例如通过b = a,这样一来代码里就会存在两个风险:

首先,因为是shallow copy,a和b中任意一个改变了他们的成员指针指向的东西,另一个实例中的指针指向的内容也将发生改变,即使这个改变并非我们的本意;

第二也是更为重要的,如果a或者b提前结束了生命周期,他们会自动call destructor,在destructor中把成员指针对应在heap中的内存delete了,这就会使得另一个实例在调用它自己的成员指针对应的内容是出错,这是非常危险的。

另外,关于operator =,有两个非常值得一提的点:

第一,例如我们在定义class A {...},那么operator =的返回值定义为&A是一个不错的选择,因为这样可以使得a = b = c这样的写法合法,当然我个人并不是很推荐这么写,我比较推荐保持代码功能的独立性;

第二,在重定义operator =的时候,排查一下输入的参数和本身调用operator的class实例是否一致是个保证程序健壮性很有必要的操作,也就是说,在编写class Sample时,这么写

Sample& Sample::operator = (const Sample& a){    if (&a != this){        [corresponding assignment operations]    }}

可以帮我们避免a = a这样的操作。

对了,顺便提一句,定义某class的copy constructor和重定义operator =时的input的类型选择const是个好习惯,因为如果我们在写其他函数的时候如果该函数要返回我们编写的class类型时,会自动调用class的copy constructor函数(没记错的话应该是copy constructor),且输入的临时变量是const class类型,这样如果copy constructor的参数类型不是const的话将报错。(const类型可以赋值给非const类型,反之不行)

0 0
原创粉丝点击