Effective C++(二):构造/析构/赋值运算

个人读书记录,不适用教学内容。

目录

条款05:了解C++默默编写并调用了哪些函数

条款06:若不想使用编译器自动生成的函数,就该明确拒绝

条款07:为多态基类声明virtual析构函数

条款08:别让异常逃离析构函数

条款09:绝不在构造和析构过程中调用virtual函数

条款10:令operator=返回一个reference to *this

条款11:在operator=中处理“自我赋值”

条款12:复制对象时勿忘每一个成分


扫描二维码关注公众号,回复: 14673106 查看本文章

条款05:了解C++默默编写并调用了哪些函数

  • default 构造函数
  • copy构造函数
  • copy assignment操作符
  • 析构函数

原文如下,值得学习:

“什么时候empty class(空类)不再是个空类?在C++处理过它后。”

有道理,这里我也加一句,什么时候C++会处理过它?是在我们使用它的时候。也就是这个类之前就是一个trivial类。

“如果你自己没声明,编译器就会为它声明一个copy构造函数,一个copy assignment操作符和一个析构函数。如果没有,也会声明一个default 构造函数。所有这些函数都是public且inline的”

书中原文剩下部分的内容大抵可总结如下:

  • 编译器为我们生成的函数都是non-virtual的(省内存)
  • 对非内置类型的copy,会以拷贝变量内的每一个bits来完成初始化(无奈之举)
  • 如果拷贝中有references,那么编译器会拒绝这个行为(引用不能更改)
  • 如果拷贝中有const,也会拒绝(const不能更改)
  • 如果base class中的copy操作符函数是private,那编译器不会为这个类生成copy操作符函数

条款06:若不想使用编译器自动生成的函数,就该明确拒绝

省流:将对应的成员函数声明为private,并且不予实现。或者如下:

条款07:为多态基类声明virtual析构函数

其实这个学过C++都应该知道的。

这里从书中get了一个新知识:string和STL容器都不被设计作为base class来使用。

另外书中的一些内容可以感觉到有些过时,提到了final,在C++11中引入了final这一关键字。而书中说C++并没有这样的关键字。

条款08:别让异常逃离析构函数

这里暂时存疑

条款09:绝不在构造和析构过程中调用virtual函数

“在构造和析构期间不要调用virtual函数,因为这类调用从不下降至derived class。(比起当前执行构造和析构的那层)。”

所以说即便我们调用了也不会得到想要的结果。

根本原因如下:

derived class构造期间,在构造base class的时期,其对象类型是base class而不是derived class

也好理解,你说这derived还没构造完呢,就开始调用virtual函数了,这能安全么?出于设计者的角度自然不会这么做,所以视derived不存在,而视为base存在。

条款10:令operator=返回一个reference to *this

没啥好说的

条款11:在operator=中处理“自我赋值”

简而言之就是说如果=两边是同一个对象(值)怎么办。

尤其涉及到在堆中分配的对象,如果一上来就把原来的指针delete掉,想去赋一个新对象,但此时新旧对象却是同一个。那就麻烦了。

所以需要特别判断一下:

或者做一个副本

 

条款12:复制对象时勿忘每一个成分

感觉没有太多好说的,直接解释原文:

  • 确保复制“对象内所有成员变量”及“所有base class成分“
  • 不要尝试以某个copy函数实现另一个copy函数,应该将共同部分放到第三个函数中,并有两个copy函数共同调用

猜你喜欢

转载自blog.csdn.net/Jason6620/article/details/128382514