类中成员变量的初始化顺序

对于类中的成员变量的初始化要注意:

考虑:

#include<iostream>
using namespace std;

class A
{
private:
    int n1;
    int n2;
    
public:

    A():n2(0),n1(n2+2){} 
    
    void Print(){
        cout << "n1:" << n1 << ", n2: " << n2 <<endl;  
    }
};

int main()
{

    A a;
    a.Print();

    getchar();
    return 1;
}

输出以上结果的时候,以为是n1:2,n2:0吗

错了!

#include<iostream>
using namespace std;

class A
{
private:
    int n1;
    int n2;
    
public:

    //A():n2(0),n1(n2+2){} //n1:-858993458, n2: 0
    //A():n1(n2+2),n2(0){}    //n1:-858993458, n2: 0
    //A():n1(0),n2(n1+2){}//n1:0, n2: 2
    A():n2(n1+2),n1(0){}//n1:0, n2: 2

    void Print(){
        cout << "n1:" << n1 << ", n2: " << n2 <<endl;  
    }
};

int main()
{

    A a;
    a.Print();

    getchar();
    return 1;
}

尝试运行以上的例子,可以发现,在用T():name(),name2():{}的形式进行初始化的时候,初始化的顺序是与类中本来类的变量位置的顺序有关,与T():name(),name2():{}的形式中变量名的顺序无关。

为什么要这样做?为什么C++不按初始化列表的顺序来初始化成员变量呢? 

因为我们知道初始化的顺序应该与析构的顺序相反,也就是说,如果有两个成员变量 A 和 B ,初始化顺序为 A -> B ,那么在这个类被析构时,应该先析构 B 再析构 A。而对一个类来说 constructor 可能有多个,初始化列表也会有多个,所以如果我们要按初始化列表的顺序来进行初始化,那么我们就得记住这个顺序,以便在析构时决定析构的顺序。所以C++就选择了简单的点的方法,按成员变量出现的顺序来初始化。

总结:既然如此,我们在写初始化列表时最好按成员变量出现的顺序来写,这样不容易出现混淆。

参考:effective C++, http://blog.sinzy.net/hjk41/entry/7998

原文地址:https://www.cnblogs.com/huhuuu/p/3484875.html