【读书笔记】Effective C++(02)构造/析构/赋值

栏目: C++ · 发布时间: 5年前

内容简介:作者:LogM本文原载于

作者:LogM

本文原载于 https://segmentfault.com/u/logm/articles ,不允许转载~

2. 构造/析构/赋值

  • 2.1 条款05:C++会自动编写default构造、拷贝构造、析构、赋值函数

    //你以为你写了个没有代码的空类
    class Empty{};
    
    // 实际上,C++自动生成了很多函数
    class Empty{
    public:
        Empty() {...}    //默认构造函数
        Empty(const Empty& rhs) {...}    //拷贝构造函数
        ~Empty() {...}     //析构函数
    
        Empty& operator=(const Empty& rhs) {...}    //赋值函数
    };
  • 2.2 条款06:声明为private防止自动生成的函数被使用

    //把拷贝构造函数和赋值函数声明为private类型,防止被使用
    class Empty {
    public:
        ...
    private:
        ...
        Empty(const Empty&);
        Empty& operator=(const Empty& rhs);
    };
  • 2.3 条款07:使用多态特性时,基类的析构函数必须为virtual

    //一个多态的场景
      class TimeKeeper {   //计时器(基类)
      public:
          TimeKeeper();
          virtual ~TimeKeeper();
          ...
      };
      class AtomicClock: public TimeKeeper {...}    //原子钟
      class WristWatch: public TimeKeeper {...}    //腕表
    
      //往往这么使用多态特性
      TimeKeeper* ptk = getTimeKeeper();
      ...
      delete ptk;

    上面是使用多态的一个场景,当 delete ptk 时,因为 ptkTimeKeeper 类型,如果基类析构函数不是 virtual ,那么 ptk 的析构时只调用基类析构函数,析构不正确;使用 virtual ~TimeKeeper(); 保证 ptk 析构时调用正确的子类析构函数

    如果一个类带有virtual函数,说明这个类有可能用于多态,那么就应该有virtual析构函数。

    不要对non-virtual析构函数的类使用多态特性,包括string、vector在内的STL容器。

    带有virtual函数的类会生成vtbl (virtual table)用于在运行期间确定具体调用哪个函数,由vptr (virtual table pointer)指向,占用空间。胡乱声明virtual会增加体积。

  • 2.4 条款08:析构函数不要抛出异常

    • 析构函数抛出异常,程序终止析构,会导致资源没有完全释放。
    //管理数据库连接的典型场景
        //如果这么写,析构函数有可能抛出异常
        class DBConn {
        public:
            ...
            ~DBConn() {
                db.close();
            }
        private:
            DBConnection db;
        }
    
        //在析构函数内捕捉异常,不要让析构函数的异常抛出
        class DBConn {
        public:
            ...
            ~DBConn() {
                try { db.close(); }
                catch (...) {
                    ...
                }
            }
        private:
            DBConnection db;
        }
  • 2.5 条款09:不在构造和析构函数中使用virtual函数

    • 构造函数在构造时,派生类的成员变量未初始化完毕,virtual函数指向基类;
    • 析构函数在析构时,派生类的成员变量部分析构,virtual函数指向基类。
  • 2.6 条款10:令 operator= 返回值为 reference to *this

    • 这么做的目的是为了实现连续赋值
    int x, y, z;
    x = y = z = 1;   //连续赋值
    
    int& operator=(const int& rhs) {
        ...
        return *this;   //返回左侧对象的引用
    }
  • 2.7 条款11:在 operator= 中处理自我赋值

    //下面代码,如果出现自我赋值,则出错
    Widget& Widget::operator=(const Widget& rhs) {
        delete elem;
        elem = new Bitmap(*rhs.elem);
        return *this;
    }
    
    //方法1
    Widget& Widget::operator=(const Widget& rhs) {
        if (this == &rhs) { return *this; }
    
        delete elem;
        elem = new Bitmap(*rhs.elem);
        return *this;
    }
    
    //方法2
    Widget& Widget::operator=(const Widget& rhs) {
        Bitmap* pOrig = elem;
        elem = new Bitmap(*rhs.elem);
        delete pOrig;
        return *this;
    }
  • 2.8 条款12:拷贝构造和赋值函数中不要遗漏成员变量

    • 编译器不检查拷贝构造和赋值函数是否对所有成员变量进行了拷贝;
    • 派生类的拷贝构造和赋值函数记得要先调用基类的拷贝构造和赋值函数。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

机器学习实战

机器学习实战

Peter Harrington / 李锐、李鹏、曲亚东、王斌 / 人民邮电出版社 / 2013-6 / 69.00元

机器学习是人工智能研究领域中一个极其重要的研究方向,在现今的大数据时代背景下,捕获数据并从中萃取有价值的信息或模式,成为各行业求生存、谋发展的决定性手段,这使得这一过去为分析师和数学家所专属的研究领域越来越为人们所瞩目。 本书第一部分主要介绍机器学习基础,以及如何利用算法进行分类,并逐步介绍了多种经典的监督学习算法,如k近邻算法、朴素贝叶斯算法、Logistic回归算法、支持向量机、AdaB......一起来看看 《机器学习实战》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具