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

class A
   2: {
private:
int i;
int j;
public:
int val )
   8:         :j ( val ), i ( j ) 
   9:     {}
  10:  
void print(){
<<j<<endl;
  13:     }
  14: };
  15:  
int main()
  17: {
  18:     A a(1);
  19:     a.print();
return 0;
  21: }

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

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

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

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

-858993460 1

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

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

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

输出的结果自然就是:

1 1

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

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

相关文章: