2.构造/析构/赋值运算
条款05:了解c++默默编写了哪些函数
编译器可以暗自为class创建default构造函数,copy拷贝构造函数,copy assignment操作符,以及析构函数,如下几点需要注意:
如果class中有引用成员,或者是const成员,编译器会拒绝为class创建拷贝函数。
编译器创建的析构函数不是虚的
条款06: 如果不想使用编译器自动生成的函数,那就该明确拒绝
上面提到,拷贝构造函数会自动生成。但是如果我们想构建一个类,这个类不允许被拷贝,该如何做呢?
最简单的方法,也是c++ iostream库中阻止copy行为的方法就是将这些函数声明为private,不用实现,只需要声明即可。这样外部就不能copy,但是friend函数和内部函数还是可以调用。但你不会这么做
还有一种方法就是定义一个uncopyable基类,基类如上操作,子类继承基类之后,如果调用copy,会先copy子类,这时候就会报错。
条款07:为多态基类声明virtual析构函数
如果基类的析构函数不是virtual的,那么基类指针指向子类对象的时,delete释放资源不会调用子类的析构函数,只会调用父类。
所以,如果定义的类带多态性质,就应该将基类析构函数设置为virtual。
但是如果不带多态性质,就别将一棍子打死全部设置为virtual析构函数,因为如果带有virtual关键字,class会多一个虚函数表。会增大类的大小
条款08:别让异常逃离析构函数
这个条款感觉不是很重要,大概就是析构函数里不要抛出异常
条款09:绝对不在构造和析构过程中调用virtual函数
在构造函数调用的时候,类当前是被认定为是基类而不是子类,这时候调用虚函数会有未定义的行为。同理,在析构的时候,子类已经被析构了,这时候类会被定义为基类。调用虚函数同样会存在问题。
但是我尝试自己编译,没有复现这个问题。之后看cpp对象模型再回顾
条款10:令operator= 返回一个reference to *this
因为c++是支持连续赋值的,所以=运算符之后需要返回一个自身的值。如果直接返回对象,那么会导致一次构造和析构函数的调用,影响性能。所以这里直接返回一个引用是很好的。
条款11:在operator=中处理自我复制
确保Operator=在任何时候都有良好的行为,首先需要比较是否就是原对象。如果是直接返回。
推广而言,一个良好的函数,在处理多个对象是同一个对象时,也有正确的行为。比如一个复制函数,首先需要函数自生的空间,然后开辟空间复制。这时候如果传入自身进入函数,就会产生问题。
处理办法就是首先开辟空间保存结果,然后再删除原来的空间
条款12:复制对象的时候不能忘记每一个值
在自己编写拷贝构造函数和拷贝运算符的时候,一定要为类的每一个成员都写好复制语句。如果没写,编译器是不会提醒你的。
不仅需要复制所有的成员,还要调用基类对象的复制构造函数或者运算符将对象完全复制。
Last updated
Was this helpful?