zoukankan      html  css  js  c++  java
  • 构造、析构、赋值运算:条款5-条款12

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

    编译器为class默认创建6个函数:

    • default构造函数
    • copy构造函数
    • move构造函数
    • copy assignment操作符
    • move assignment操作符
    • 析构函数
    struct A { 
        A() {}                                                 //default构造函数
        A(const A& a) {}                                //copy构造函数
        A(A&& a) {}                                       //move构造函数
        A& operator=(const A& other) {}      //copy assignment操作符
        A& operator=(A&& a) {}                    //move assignment操作符
        ~A() {}                                              //析构函数
    };
    
    • 如果自己构造了带参数的构造函数,编译器不会产生default构造函数
    • base class如果把拷贝构造函数或者赋值操作符设置为private,不会产生这两个函数
    • 含有引用成员变量或者const成员变量不产生赋值操作符
    class NamedObject{
    private:
        std::string& str;//引用定义后不能修改绑定对象
        const std::string con_str;//const对象定义后不能修改
    };
    

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

    将默认生成的函数声明为private,或者C++ 11新特性"=delete"

    class Uncopyable{
        //Uncopyable(const Uncopyable&) = delete;                        //拒绝使用默认
        //Uncopyable& operator= (const Uncopyable&) = default;   //使用默认
    private:
        Uncopyable(const Uncopyable&);
        Uncopyable& operator= (const Uncopyable&);
    }
    

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

    • 给多态基类应该主动声明virtual析构函数
      • 当子类对象经由一个父类指针删除时,如果父类带有一个non-virtual析构函数,可能会使得对象的子类成分没有被销毁。
    • 非多态基类,没有virtual函数,不要声明virtual析构函数
      • 没有virtual函数的类一般不做基类,为其声明vitual会导致在创建对象时,C++编译器会给对象添加一个vptr指针,类中创建的虚函数的地址会存放在一个虚函数表中,vptr指针就是指向這个表的首地址。

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

    • 析构函数绝对不要突出异常
      • 析构函数抛出异常会导致程序提前结束、不明确行为、内存泄漏(构造函数抛出异常不会引起内存泄露)
      • 如果一个被析构函数调用的函数可能抛出异常,析构函数中要及时捕捉异常并吐下他们(防止传播)或结束程序
    Base::~Base() {
        try {function();}
        catch(...) {
            //记录function调用失败
            std::abort();
        }
    }
    

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

    在调用子类构造函数时,会先调用父类构造函数。
    父类构造期间,父类成员初始化,且子类成员尚未初始化,虚表指针指向父类的虚函数表,此时调用的虚函数都是父类的函数。
    父类构造完成后,初始化子类成员,虚表指针指向子类虚函数表,此时调用的虚函数是子类的函数。

    条款10:令赋值(assignment)返回一个reference to *this

    为了实现赋值连锁形式

    x=y=z=15;    //赋值连锁
    
    // 返回 reference to *this
    Widget& operator=(const Widget& ths) 
    {
        ...
        return* this;
    }
    // operator += 等等要遵循
    

    条款11:在operator=中实现“自我赋值”

    Widget& Widget::operator== (const Widget& rhs){
        if(this == &rhs) return *this
        
        ···
    }
    

    条款12:复制对象时勿忘其每一部分

    • 记得实现copy构造函数和copy赋值操作符的时候,调用base的相关函数
    • 可以让拷贝构造函数和赋值操作符调用一个共同的函数,例如init
  • 相关阅读:
    Windows XP下安装和配置Apache2.2.22服务器+PHP5+Mysql5
    win7下80端口被(Pid=4)占用的解决方法
    netty入门实例
    java NIO经典实例
    Eclipse下快速打开本地文件插件EasyExplorer(转)
    Nexus配置
    Maven依赖(转)
    【原创】C#玩高频数字彩快3的一点体会
    【原创】.NET读写Excel工具Spire.Xls使用(2)Excel文件的控制
    【踩坑经历】一次Asp.NET小网站部署踩坑和解决经历
  • 原文地址:https://www.cnblogs.com/narjaja/p/10067735.html
Copyright © 2011-2022 走看看