对于类中的成员变量的初始化要注意:
考虑:
#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