没有初始化列表与初始化列表,空括号对

时间:2013-10-16 15:15:59

标签: c++ initializer-list

这是来自此主题Initializing fields in constructor - initializer list vs constructor body

的复制粘贴

作者解释了以下等同性:

    public : Thing(int _foo, int _bar){
        member1 = _foo;
        member2 = _bar;
    }

is equivalent to

    public : Thing(int _foo, int _bar) : member1(), member2(){
        member1 = _foo;
        member2 = _bar;
    }

我的理解是

  • 片段1是默认初始化的情况(因为没有初始化列表)
  • 片段2是值初始化(空对括号)的情况。

这两个是如何相同的?

2 个答案:

答案 0 :(得分:3)

您的理解是正确的(假设member1member2 有类型`int)。这两种形式是等价;在里面 首先,成员根本没有初始化,也不可能 使用直到他们被分配。在第二种情况下, 成员将初始化为0.这两个配方只是 如果成员是具有用户定义的类类型,则等效 构造函数。

答案 1 :(得分:1)

你说得对,但作者也是有点了!

您的解释完全正确,其他人给出的答案也是如此。总之,如果member1member2是非POD类型,则两个代码段是等效的。

对于某些POD类型,它们在某种意义上也是等同的。好吧,让我们再简化一下,假设member1member2的类型为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);
使用选项-O1使用GCC 4.8.1

。 (__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。这些额外的行将两个成员初始化为零。