《Effective C++第三版》读书笔记——构造/析构/赋值运算

来源:互联网 发布:js控制视频播放 编辑:程序博客网 时间:2024/06/07 11:21

2 构造/析构/赋值运算
~~~~~~~~~~~~~~~~~~~~~

2.1 了解C++默认编写并调用哪些函数
==================================
   1. 如果自己没有声明,编译器会自动声明一个copy构造函数,一个copy assignment操作符和一个析构函数.
      如果没有声明任何构造函数,编译器也会自动声明一个default构造函数
   2. 注意:编译器产生的析构函数是个non-virtual,除非这个class的base class自身声明有virtual析构函数(这时这个函数的虚属性,主要来自base class)
   3. 编译器自动生产的copy构造函数和copy assignment操作符会尝试调用基类的对应函数,因此如果某个基类将copy assignment操作符申请为private,编译器将拒绝为其子类生成一个copy assignment操作符

2.2 若不想使用编译器自动生成的函数,就该明确拒绝
================================================
   1. 若想阻止类的copy行为,可以将copy构造函数和copy assignment操作符声明为private,并且故意不去实现它们.那么如果某些人不慎调用任意一个函数,都会获得一个链接错误.
      或则也可以将该类继承至一个copy构造函数和copy assignment操作符为private的基类.因为正如上一条所说的,编译器自动生产的copy构造函数和copy assignment操作符会尝试调用基类的对应函数,而这些基类是private的,会被编译器拒绝.
 

  1. class Uncopyable{ 
  2.   protected
  3.       Uncopyable(){} 
  4.       ~Uncopyable(){} 
  5.   private
  6.       Uncopyable(const Uncopyable&); 
  7.       Uncopyable& operator=(const Uncopyable&); 
  8.   } 



2.3 为多态基类声明virtual析构函数
==================================
   1. 当子类对象经由一个基类指针删除,而该基类带有一个non-virtual析构函数,其结果未定义.通常发生的是对象的derived成分没被销毁.
   2. 一般只有当class内含有至少一个virtual函数时,才将析构函数声明为virtual.因为一个class不含virtual函数往往说明它不愿意被当作基类(C++没有类似finally这样的禁止派生机制),这时使用virtual析构函数只是增大体积而已.
   3. std::string和所有的STL容器都有个non-virtual析构函数,因此继承它们是个搜主意
   4. class的设计目的如果不是作为基类使用,或不是为了具备多态性,就不该声明virtual析构函数
   5. 析构函数的运行方式是,子类的析构函数先被调用,然后父类的析构函数被隐性调用

2.4 析构函数不要抛出异常
=========================
   1. 可以将会抛出异常的析构函数中的操作封装为一个普通函数提供给客户,使客户有机会捕获异常并处理它.

2.5 绝不要在构造和析构函数过程中调用virtual函数
================================================
   1. 在基类的构造期间,virtual函数不是virtual函数,它执行的还是基类版本的函数!!因为在子类对象的base class构造期间,改对象的类型是base class而不是子类.
      某个对象的子类部分没有初始化,因此最后的做法就是视他们不存在,把对象当基类看.

2.6 令operator=返回一个reference to *this
==========================================
   1. 为了实现连续赋值,赋值操作符必须返回一个reference指向操作符的左侧实参.

2.7 在operator=中处理自我赋值
==============================
   1. 传统做法是在operator=最前面做一个证同测试,达到自我赋值的检测目的.然而这种方法不具备异常安全性
   2. 使用所谓的copy and swap技术.过程是首先为右值制作一个副本,然后将*this上的数据和副本的数据交换.

2.8 复制对象时别忘了其没一个成分(尤其是父类的成分)
===================================================
   1. 只要需要手工编写derived class的copying函数(copy构造函数和copy assignment操作符),就必须很小心地复制其base class成分.那些成分往往是private的,所以你可能无法直接访问它们,你应该让derived class的copying函数调用相应的base class函数.
 

  1. Derived::Derived(const Derived& rhs):Base(rhs)   //调用base的copy构造函数 
  2.   Derived& Derived::operator=(const Derived& rhs) 
  3.   { 
  4.       Base::operator=(rhs)                         //对base class成分进行赋值操作 
  5.   } 



   2. 不要在copy assignment操作符中调用copy构造函数,也不要在copy构造函数中调用copy assignment操作符,
      构造函数用来初始化新对象,而assignment操作符只施行于已初始化的对象上,这两者互用是不合理的.

本文出自 “暗日” 博客,请务必保留此出处http://darksun.blog.51cto.com/3874064/1144743

0 0