关于构造方法的一个有趣的问题:初始化队伍

下面这段代码是有问题的,问题当然是关于构造方法:

   1: class A
   2: {
   3: private:
   4:     int i;
   5:     int j;
   6: public:
   7:     A ( int val )
   8:         :j ( val ), i ( j ) 
   9:     {}
  10:  
  11:     void print(){
  12:         cout<<i<<" "<<j<<endl;
  13:     }
  14: };
  15:  
  16: int main()
  17: {
  18:     A a(1);
  19:     a.print();
  20:     return 0;
  21: }

构造方法的实现很简单:先将val的值赋给j,再将j赋值给i。

但事实上并没有达到这个效果。

这里有一个初始化队伍的问题。初始化队伍这里指的就是构造方法中冒号后面的部分。

编译器在处理初始化队伍时,会根据成员变量的声明次序重新排序。也就是说,虽然构造方法是先对j进行初始化,但是,根据i和j的声明次序,实际上是先对i初始化,然后再对j进行初始化。这样一来,由于j还未初始化,所以最终的结果是i的值并不是val。下面是我在visual studio 2010下输出的结果:

-858993460 1

这种问题是很难发现的,要修正很简单,只需要将构造方法写为:

   1: A ( int val )
   2:     :j ( val )
   3: {
   4:     i = j;
   5: }

这里,还存在另一个知识点:执行初始化队伍( j(val) )在执行任何显式代码(explicit user code)之前,这里指的就是“i=j”。所以,就是先令j=val,然后令i=j。

输出的结果自然就是:

1 1

所以建议,如果是用一个数据成员对另一个数据成员进行初始化,即赋值,最好是把这样的代码写在构造函数体内(显式代码)。

参考文献:《深度探索C++对象模型》

posted @ 2011-05-22 15:19  AnnieKim  阅读(652)  评论(0编辑  收藏  举报