zoukankan      html  css  js  c++  java
  • 条款05:了解C++默默编写并调用哪些函数

    每一个class都会有一个或多个构造函数、一个析构函数、一个copy assignment操作符。这些控制着基础操作,像是产出新对象并确保它被初始化、摆脱旧对象并确保它被适当清理、以及赋予对象新值。

    那么当你当你编写了一个empty class的时候,当你利用编译器的对代码进行处理的时候,它其实已经并非是一个empty  class 了。编译器会悄悄的给你生成了default 构造函数、一个析构函数、一个copy构造函数和一个copy assignment操作符,并且它们都是inline的(隐式inline)。如下代码示例

    一个自定类: class empty{}; 
    

      其实等于以下代码:

    class Empty { 
    public:
    Empty() { }//default 构造函数
    
    ~Empty() { }//析构函数
    Empty(const Empty& rhs) { }//copy构造函数
    Empty& operator=(const Empty& rhs) { }//copy assignment操作符
    }; 
    

      注意:上面的重载的操作运算符operator=的返回值是对象的引用,条款21似乎说了不要妄想返回对象的引用,这篇文章的意思不是说不能返回对象的引用,而是当你要返回对象的引用的时候,要确定引用的本体是谁,它能否被合理的delete

    那么这四个名词的概念分别是:
    default 构造函数:在你不提供任何构造函数的情况下,系统给出的一个不带参数,不包含函数代码的构造函数;但是当你声明了一个构造函数,编译器就不再为它创建default构造函数了。
    析构函数:与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,应在退出前在析构函数中用delete释放)。
    copy构造函数:只有单个形参,而且该形参是对本类类型对象的引用(常用const修饰),这样的构造函数成为构造函数(C++ pirmer定义)。经常被称作X(const X&),而且也是由编译自动调用。
     
    copy assignment操作符:自动合成的一种赋值操作符。
     
    什么时候会调用copy构造函数

    以下三种情况出现时,会调用一个类的拷贝构造函数:
    1) 用一个已经实例化了的该类对象,去实例化该类的另外一个对象;
    2) 用该类的对象传值的方式作为一个函数的参数;
    3) 一个函数返回值为该类的一个对象。
     
    编译器在copy构造函数被需要(被调用),copy构造函数才会被编译器创建出来,但是注意,编译器产出的析构函数是个non-virtual,除非这个class的base class自身声明有virtual析构函数(这种情况下这个函数是虚属性)。
     
    什么时候不会自动调用copy assignment操作符?
     
    至于copy构造函数和copy assignment操作符,编译器创建的版本只是单纯地将来源对象的每一个non-static成员变量拷贝到目标对象。但在某些情况下编译器拒绝生成copy assignment操作符函数。比如存在引用成员和const成员。对于引用的改变,也就是说引用自身可被改动吗?如果是,那么就违背了C++的原则:引用不能修改指向对象。所以必须自己定义copy assignment操作符。但是对于copy构造函数,没有这方面的担心,因为对象里的引用或者const成员还没有被初始化。比如如下代码:
    #include <iostream>  
      
    using namespace std;  
      
    class Person 
    {  
    public:  
      
        Person(string& a, const int& b) : name(a), id(b) { }  
      
    private:  
      
        const int id;  
        string& name;  
      
    };  
      
    int main() 
    {  
        Person p1(string("chu"), 1);  
      
        Person p2(string("jun"), 2);  
      
        p1 = p2;/////// error C2582: 'operator =' function is unavailable in 'Person'  
      
        system("pause");  
      
        return 0;  
    } 
    

      还有一种情况编译器不会生成copy assignment函数,就是基类将copy assignment声明为private,派生类型就无法获得编译器的帮助,因为编译器为derived classes所生成的copy assignment操作符要处理base class成分。因为派生类型无法调用基类型的copy assignment函数(不具备访问权限)。

    #include <iostream>
    
    using namespace std;
    
    class BaseClass 
    {
    
    private:
    
        BaseClass& operator=(const BaseClass& rhs) { }
    
    };
    
    
    class derived : public BaseClass { };
    
    
    int main() 
    {
    
        BaseClass px1, px2;
    
        px1 = px2; ///// 'BaseClass::operator =' : cannot access private member declared in class 'BaseClass'
    
        system("pause");
        return 0;
    
    }  
    

      所以,请记住:

    编译器可以暗自为class创建default构造函数,copy构造函数,copy assignment操作符,以及析构函数。

  • 相关阅读:
    蚂蚁
    N的阶乘
    最小公倍数LCM
    最大公约数GCD
    Truck History(卡车历史)
    亲戚
    [SDOI2011]打地鼠
    连续自然数和
    P4250 [SCOI2015]小凸想跑步
    P4048 【[JSOI2010]冷冻波】
  • 原文地址:https://www.cnblogs.com/stemon/p/4583462.html
Copyright © 2011-2022 走看看