Effective C++第三版之(二)Constructors, Destructors, and Assignment Operators

Constructors, Destructors, and Assignment Operators.构造/析构/赋值运算

条款5:Know what functions C++ silently writes and calls.了解C++默认生成与调用
1,如果没有声明,编绎器会自动生成copy构造函数和copy assignment运算符及析构函数,如果没声明任何构造函数,编绎器会自动生成default构造函数,声明为public且inline,且只有在调用时才会自动生成。
2,default构造函数和析构函数会调用base classes和non-static成员变量的构造函数和析构函数,编绎器生成的析构函数是个non-virtual,如果基类析构函数是virtual的,则类的析构函数也是virtual。
3,copy构造函数将来源对象的non-static成员变量拷贝到目标对象,自定义类型成员变量调用自己的copy构造函数完成初始化,内置类型拷贝每个bits完成初始化。
4,copy assignment运算符行为上与copy构造函数一致,但类内成员变量为引用或const时,不可使用自动生成的copy assignment运算符,需要自定义copy assignment运算符。
5,如果base classes将copy assignment运算符声明为private,编绎不会为derived classes生成copy assignment运算符。

条款6:Explicitly disallow the use of compiler-generated functions you do not want.显示禁止不想使用的编绎器生成函数。
1,编绎器生成的构造函数和运算符是public,将此类函数声明为private,可阻止类外调用,成员函数和friend函数可调用。
2,声明为private但不定义,成员函数调用此类函数报连接错误,C++ iostream程序库中阻止copying行为便是将copy构造函数和copy assignment运算符声明为private且不定义。
3,将阻止copying动作设计到base class内,可将连接错误移至编绎期,编绎器尝试为derived class生成copy构造函数或copy assignment运算符,需要调用base class的对应函数,因base class对应函数是private调用被拒绝,编绎器为derived class生成函数失败,成员函数调用此类函数报编绎错误。
4,Uncopyable class通常为base class,不一定以public继承,析构函数不一定是virtual,可以不含数据。

条款7:Declare destructors virtual in polymorphic base classes.在多态基类中声明虚析构函数
1,设计工厂函数,返回一个base class指针,指向新生成之derived class对象。
1)如果此对象位于heap,工厂函数返回的每个对象需要delete,但是工厂函数返回的指针指向derived class对象,却由一个base class指针删除,执行base class的non-virtual析构函数导致对象的derived成分不被销毁,derived class的析构函数未能执行,造成局部销毁对象的资源泄漏。
2)声明base class析构函数为virtual,删除derived class对象执行derived class的析构函数,通过base class接口处理derived class对象。
2,base classes除了虚析构函数外其他virtual函数,目的是允许derived class实现特例化,实现多态目的。当class内至少有一个virtual函数,需要声明virtual析构函数。
3,若class不含virtual函数,不意图作为base class,不建议令析构函数为virtual,含有virtual函数的类内会增加一个vptr指针对象。
4,class声明pure virtual析构函数,即抽象class,pure virtual析构函数需要定义为空,析构函数调用时最深层派生class析构函数先被调用,然后是每个base class析构函数被调用,所以需要在抽象基类纯虚析构函数提供一份空定义。
总结:
1)多态目的的base classes需要声明virtual析构函数,如果class带有任何virtual函数,析构函数必须声明为virtual。
2)若classes不是多态目的的base classes或不是base classes,不建议声明virtual函数。

条款8:Prevent exceptions from leaving destructors.防止异常离开析构函数
1,C++不禁止析构函数抛出异常,但不建议这样做。析构函数抛出异常会带来不明确行为的风险。
2,如果析构函数捕捉到异常则需要阻止异常传播,可强迫结束程序或吞下异常,强迫结束程序会过早结束程序,吞下异常则隐藏了异常信息。
3,设计普通函数执行捕捉异常的操作,并对抛出的异常作出反应。

条款9:Never call virtual functions during construction or destruction.绝不在构造和析构函数过程中调用virtual函数
1,base class构造期间,virtual函数不是virtual函数。base class构造函数的执行早于derived class构造函数,derived class成员变量尚未初始化,使用类内未初始化成员将产生不明确行为,所以virtual函数不会下降到derived classes层。
2,derived class对象的base class构造期间,对象类型是base class而不是derived class,不只virtual函数会被编绎器解析至base class,若使用运行期类型信息(例dynamic_cast)也会将对象视为base class类型。
3,derived class对象在derived class构造函数执行前不会成为derived class对象。同样derived class析构函数开始执行,对象内的derived class成员变量开始呈现未定义值,进入base class析构对象后对象就成为base class对象。
4,构造函数和析构函数在对象创建和销毁期间调用的其他函数也不可调用virtual函数。

条款10:Have assignment operators return a reference to *this.令operator=返回一个reference to *this
1,赋值运算符采用右结合律,返回左侧运算对象的左值引用,可连锁赋值。
2,其他复合赋值相关运算符需遵循返回左侧运算对象的左值引用。

条款11:Handle assignment to self in operator=.在operator=中处理自我赋值。
1,copying动作可使用成员的赋值操作也可使用copy构造函数,使用copy构造函数可令编绎器生成更高效的代码。
2,使用copy构造函数构造成员对象,需要先析构自身,则处理自我赋值时需要增加证同测试,但证同测试需要成本,代码变大并导入新的控制流分支,降低执行速度。
3,确保代码安全且自我赋值安全的替代方案是使用copy and swap技术,swap交换自身与赋值对象的副本。

条款12:Copy all parts of an object.复制对象所有部分
1,面向对象系统会将对象的内部封装起来,只留copy构造函数和copy assignment运算符,编绎器也会为classes生成合成版本,拷贝所有成员的变量。
2,自定义copying函数,需要复制对象所有成员,derived class调用base class的copying函数复制base class成员。
3,copy构造函数和copy assignment不可互相调用,声明另一个成员函数给两者调用消除重复代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值