美文网首页
浅谈成员初始化列表

浅谈成员初始化列表

作者: 404Not_Found | 来源:发表于2021-08-24 22:48 被阅读0次
    • 作者: 雪山肥鱼
    • 时间:20210825 22:29
    • 目的: 成员初始化列表的作用

    何时需要成员初始化列表

    class Base
    {
    public:
        int ba;
        int bb;
        Base(int tmpa, int tmpb)
        {
        }
    };
    
    class CSub
    {
    public:
        CSub(int tmpv)
        {
    
        }
    };
    
    class A:public Base
    {
    public:
        int m_x;
        int m_y;
        int &m_yy;
        const int m_myc;
        CSub cmysub;
        //A() :m_x(0), m_y(0)
        A(int &tmpvalue):m_yy(tmpvalue), m_myc(tmpvalue),Base(tmpvalue, tmpvalue), cmysub(tmpvalue)
        {
            //m_myc = tmpvalue;
            //m_yy = tmpvalue;
            m_x = 0;
            m_y = 0;
            m_yy = 180;
        }
    };
    
    int main(int argc, char ** argv)
    {
      int abc =1;
      A a(abc);
    }
    

    下述情况必要参数初始化列表

    1. 成员变量有引用
    2. 成员变量 是 const 类型
    3. 如果继承一个基类,且积累中有自定义的含参数构造函数
    4. 成员变量的类型是对象,且 这个类中有自己的带参数的自定义构造函数

    参数列表各种试错:


    试错.png

    参数初始化列表的作用

    无参数初始化列表

    class X
    {
        public:
            int m_i;
            X(int value = 0):m_i(value)
            {
                cout <<"X(int)"<<" this: "<< this<<endl;
            }
            X(const X& tmp)
            {
                cout<<"Copy X(const &)"<<" this: "<<this<<endl;
            }
            X & operator=(const X &tmp)
            {
                cout<<"Operator=(const X & tmp)"<<" this: "<<this<<endl;
            }
            ~X()
            {
                cout<<"X destructor"<<" this: "<<this<<endl;
            }
    };
    
    
    class A
    {
        public:
            X xobj; 
            int m_test;
        
            /*
             X xobj;
             xobj.X::X(int tmp);
            */
    
            A(int tmpvalue)//走到这里的时候 xobj 被构造
            {
                /*
                X tmp; 
                tmp.X::X(1000); 
                xobj.X::operator=(tmp);
                tmp.X::~X();
                */
    
                xobj = 1000; //xobj 已经存在,增加 3个动作 :所以先用1000 构造一个 tmp, 然后调用operator=,最后析构
                m_test = 500;
            }
        
    };
    
    int main(int argc, char **argv)
    {
        
        A myaobj(1000);
        return 0;
    }
    
    运行结果.png

    其实只因为 一句话 xobj = 1000 就会多出3个动作,注意这里走到 这一行的时候, xobj 已经生成了,因为 X类 的构造函数是有默认参数的。
    三个动作在代码的注释已经说明。另外可以观察到临时对象和 对象 xobj 的地址并不相同!

    带有参数初始化列表

    class A
    {
        public:
            X xobj; 
            int m_test;
            int m_test2;
            
            A(int tmpvalue):xobj(1000)
            {
            }
        
    };
    

    运行结果,会减少上一节中的三个步骤。

    单步调试就可以知道,参数初始化列表是在本类的构造函数之前执行的!

    变量的初始化顺序是定义顺序,而不是参数列表初始化顺序

    class A
    {
        public:
            X xobj; 
            int m_test;
            int m_test2;
            
            A(int tmpvalue):xobj(1000),m_test2(100),m_test(m_test2)
            {
            }
        
    };
    
    1. m_test 先被初始化
    2. m_test2 后被初始化
    3. 如果像构造函数一样的顺序,则m_test还未被初始化的时候,m_test 就被赋予了垃圾值。
    4. 并不是我们想要的结果。
    5. 简单成员变量,建议在构造函数内部初始化,就不必在意顺序啦。

    相关文章

      网友评论

          本文标题:浅谈成员初始化列表

          本文链接:https://www.haomeiwen.com/subject/waaeiltx.html