构造函数初始化必须采用初始化列表的情况

转自:https://blog.csdn.net/u012611878/article/details/79200544

https://my.oschina.net/assange/blog/542896

1.赋值与初始化

初始化为变量分配空间,一般变量是在编译时根据定义初始化;赋值是擦除旧值与写入新值的过程,没有空间的分配。

2.const/引用类型

当成员变量是const类型或者引用时,必须通过初始化列表初始化,而不能放在构造函数体中(这样就是赋值了),因为const和引用类型的变量必须声明时初始化。

static数据成员需要在类外初始化,int CSomeClass::myVar=3; static变量应该在类的构造函数前被初始化。

3.对象,且没有默认构造函数

数据成员是对象,且没有默认的构造函数。例子:

class Test
{
    public:
        Test (int, int, int){
        cout <<"Test" << endl;
    }
 private:
    int x;
    int y;
    int z;
};

class Mytest
{
 public:
    Mytest():test(1,2,3){       //初始化ok
        //test(Test(1,2,3));//error: no match for call to '(Test) (Test)'
        //test=Test(12,3,4);//error: no matching function for call to 'Test::Test()'
//test(1,2,3);//error: no match for call to '(Test) (int, int, int)'
cout << "Mytest" << endl; }//注:在尝试下面三个时,初始化列表已删掉 private: Test test; //声明 };

错误1:尝试在内部初始化,不行

错误2:尝试在内部通过赋值的方式初始化,但没有默认的构造函数,即参数列表为空,那么test就会首先被默认初始化,但是Test类没有默认的构造函数从而出现错误,所以初始化只能放在列表中。

4.子类初始化父类私有成员

class Test{
public:
    Test(){}
    Test (int x){ int_x = x;}
    void show(){cout<< int_x << endl;}
private:
    int int_x;
};

class Mytest:public Test{
public:
    Mytest():Test(110){//打印出110 
      //Test(110);            //  构造函数只能在初始化列表中被显示调用,不能在构造函数内部被显示调用 。不报错但打印随机数:14887136
    }
};
int main(){
     Test *p = new Mytest();
     p->show();
         return 0;
}

 

5.初始化列表效率更高

使用初始化列表是直接初始化,而在函数体内是先初始化再赋值。存在效率的差异,如果是类对象,那么效率更低。

注意:不论是否出现在初始化列表中,变量都会被在此处按照声明顺序进行初始化,所以为了保证效率,最好初始化列表顺序与声明顺序一致。

为什么变量的初始化顺序是按照声明而不是初始化列表的顺序?

因为需要考虑到析构的过程,析构按照构建的相反顺序,如果参照初始化列表的话,还需要再额外维护一个顺序,开销太大。

 

posted @ 2021-04-10 16:47  lypbendlf  阅读(255)  评论(0编辑  收藏  举报