你是对的,但作者也是对的!
您的解释是完全正确的,其他人给出的答案也是如此。总之,如果member1
和member2
是非 POD 类型,这两个片段是等价的。
对于某些 POD 类型,它们在某种意义上也是等价的。好吧,让我们再简化一点,假设member1
有member2
type int
。然后,根据as-if-rule ,允许编译器将第二个片段替换为第一个片段。member1
实际上,在第二个片段中,首先初始化为的事实0
是不可观察的。只有它的任务_foo
是。这与允许编译器替换这两行的原因相同
int x = 0;
x = 1;
有了这个
int x = 1;
例如,我编译了这段代码
struct Thing {
int member1, member2;
__attribute__ ((noinline)) Thing(int _foo, int _bar)
: member1(), member2() // initialization line
{
member1 = _foo;
member2 = _bar;
}
};
Thing dummy(255, 256);
使用 GCC 4.8.1 选项-O1
。(__atribute((noinline))__
阻止编译器内联函数)。那么无论初始化行是否存在,生成的汇编代码都是相同的:
-O1
有或没有初始化
0: 8b 44 24 04 mov 0x4(%esp),%eax
4: 89 01 mov %eax,(%ecx)
6: 8b 44 24 08 mov 0x8(%esp),%eax
a: 89 41 04 mov %eax,0x4(%ecx)
d: c2 08 00 ret $0x8
另一方面,当使用-O0
汇编代码编译时,根据初始化行是否存在而有所不同:
-O0
没有初始化
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 04 sub $0x4,%esp
6: 89 4d fc mov %ecx,-0x4(%ebp)
9: 8b 45 fc mov -0x4(%ebp),%eax
c: 8b 55 08 mov 0x8(%ebp),%edx
f: 89 10 mov %edx,(%eax)
11: 8b 45 fc mov -0x4(%ebp),%eax
14: 8b 55 0c mov 0xc(%ebp),%edx
17: 89 50 04 mov %edx,0x4(%eax)
1a: c9 leave
1b: c2 08 00 ret $0x8
1e: 90 nop
1f: 90 nop
-O0
带初始化
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 04 sub $0x4,%esp
6: 89 4d fc mov %ecx,-0x4(%ebp)
9: 8b 45 fc mov -0x4(%ebp),%eax ; extra line #1
c: c7 00 00 00 00 00 movl $0x0,(%eax) ; extra line #2
12: 8b 45 fc mov -0x4(%ebp),%eax ; extra line #3
15: c7 40 04 00 00 00 00 movl $0x0,0x4(%eax) ; extra line #4
1c: 8b 45 fc mov -0x4(%ebp),%eax
1f: 8b 55 08 mov 0x8(%ebp),%edx
22: 89 10 mov %edx,(%eax)
24: 8b 45 fc mov -0x4(%ebp),%eax
27: 8b 55 0c mov 0xc(%ebp),%edx
2a: 89 50 04 mov %edx,0x4(%eax)
2d: c9 leave
2e: c2 08 00 ret $0x8
31: 90 nop
32: 90 nop
33: 90 nop
请注意,-O0
与没有初始化相比,使用初始化有四个额外的行(如上标记)-O0
。这些额外的行将两个成员初始化为零。