类成员的初始化是有顺序的,不注意是要有大问题的。看下面的例子:
class C
{
public:
int a;
int b;
public:
C():b(1),a(b)
{ }
};
C c;
printf("%d, %d",c.a,c.b);
那么c.a等于1吗?
结果实际上是没有定义。
看一下编译器(VC2008)的汇编代码:
00901A83 mov eax,dword ptr [this]
00901A86 mov ecx,dword ptr [this]
00901A89 mov edx,dword ptr [ecx+4]
00901A8C mov dword ptr [eax],edx
00901A8E mov eax,dword ptr [this]
00901A91 mov dword ptr [eax+4],1
可以看到赋1给b的是在最后一部,而a的赋值却在前(见0901A89),这个时候b的值[ecx+4]是没有定义的。
那为什么这样?
这是因为C++标准规定成员初始化顺序是按照声明的顺序决定,因此最后编译帮我们声明了上面的代码。
如果一定要先给b赋值,怎么办?
可以这么做:
C():b(1)
{
a = b;
}
再来看反汇编代码:
00A01A80 mov dword ptr [ebp-8],ecx
00A01A83 mov eax,dword ptr [this]
00A01A86 mov dword ptr [eax+4],1
a = b;
00A01A8D mov eax,dword ptr [this]
00A01A90 mov ecx,dword ptr [this]
00A01A93 mov edx,dword ptr [ecx+4]
00A01A96 mov dword ptr [eax],edx
这里可以看到b先被赋值,而a由于不在成员初始化列表中,所以放在随后被赋值。