第二章 构造/析构/赋值运算
5、了解 C++ 默默编写并调用哪些函数
编译器可以隐式为类创建:默认构造函数、复制构造函数、赋值构造函数、析构函数。
6、若不想使用编译器自动产生的函数,就应该明确拒绝
拒绝的方法是:把函数设为 private,只有声明没有实现。但 member 函数和 friend 函数还是可以调用 private 函数,由于没有实现,会在连接期报错,不利排插,讲错误移至编译期的方法是:private 继承 Uncopyable 类,Boost 也有个类,名为 noncopyable。
7、为多态基类声明 virtual 析构函数
任何类只要带有 virtual 函数,都几乎确定应该有一个 virtual 析构函数。但有 virtual 函数会降低调用效率和可优化性,所以能不用则不用,比如说,某个类没有考虑作为基类(base class)被继承,则没有必要有 virtual 析构函数,STL 的容器大多如此。
8、别让异常逃离析构函数
如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下他们或者结束程序。
如果客户需要对某个函数运行期间抛出的异常做出反应,那么类应该提供一个普通函数执行该操作,而非在析构函数中。
9、绝不在构造和析构过程中调用 virtual 函数
因为这类调用从不降至派生类(derived class),它将调用本层的函数。
10、令 operator= 返回一个 reference to *this
这样才能支持连锁赋值,a = b = c = d。
11、在 operator= 中处理“自我赋值”
方法有:比较来源和目标对象的地址、精心周到的语句顺序、copy-and-swap。要考虑自我赋值的概率,如果很小,则比较地址的方式可能并不好,因为无视它效率更高。
12、复制对象时勿忘其每一个成分
复制函数应该保证复制“对象内的所有成员变量”及“所有基类成分”。当你编写一个复制函数,请确保(1)复制所有 local 成员变量,(2)调用所有基类内的适当的复制函数。
不要尝试以某个复制函数实现另一个复制函数。应该将共同机能放进第三个函数中,并由两个复制函数共同调用。