简体   繁体   English

没有初始化程序列表与带有空括号对的初始化程序列表

[英]No initializer list vs. initializer list with empty pairs of parentheses

This is copy paste from this topic Initializing fields in constructor - initializer list vs constructor body 这是该主题的复制粘贴。 初始化构造函数中的字段-构造函数列表与构造函数主体

The author explains the following equivalence: 作者解释了以下等效性:

    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;
    }

My understanding was that 我的理解是

  • snippet 1 is a case of default-initialization (because of the absence of an initializer list) 片段1是默认初始化的情况(由于缺少初始化列表)
  • snippet 2 is a case of value-initialization (empty pairs of parentheses). 片段2是值初始化(空对括号)的情况。

How are these two equivalent? 这两个当量如何?

Your understanding is correct (assuming member1 and member2 have type `int). 您的理解是正确的(假设member1member2类型为int)。 The two forms are not equivalent; 这两种形式是等价的。 in the first, the members are not initialized at all, and cannot be used until they have been assigned. 在第一个实例中,成员根本没有初始化,并且只有在分配成员后才能使用。 In the second case, the members will be initialized to 0. The two formulations are only equivalent if the members are class types with user defined constructors. 在第二种情况下,成员将初始化为0。仅当成员是具有用户定义的构造函数的类类型时,这两个公式才等效。

You are right but the author is kind of right too! 你是正确的,但笔者是一种权利呢!

Your interpretation is completely correct as are the answers given by others. 您的解释完全正确,其他人给出的答案也一样。 In summary the two snippets are equivalent if member1 and member2 are non-POD types. 总之,如果member1member2是非POD类型,则这两个代码段是等效的。

For certain POD types they are also equivalent in some sense . 对于某些POD类型,它们在某种意义上也是等效的。 Well, let's simplify a little more and assume member1 and member2 have type int . 好吧,让我们简化一些,并假设member1member2类型为int Then, under the as-if-rule the complier is allowed to replace the second snippet with the first one. 然后,在常规规则下允许编译器将第一个代码段替换为第二个代码段。 Indeed, in the second snippet the fact that member1 is first initlialized to 0 is not observable. 确实,在第二个片段中,无法观察到member1首先被初始化为0的事实。 Only its assignment to _foo is. 仅将其分配给_foo This is the same reasoning that allows the compiler to replace these two lines 这是允许编译器替换这两行的相同原因。

int x = 0;
x = 1;

with this one 与这个

int x = 1;

For instance, I've compiled this code 例如,我已经编译了这段代码

struct Thing {

    int member1, member2;

    __attribute__ ((noinline)) Thing(int _foo, int _bar)
        : member1(), member2() // initialization line
    {
        member1 = _foo;
        member2 = _bar;
    }
};

Thing dummy(255, 256);

with GCC 4.8.1 using option -O1 . 在GCC 4.8.1中使用选项-O1 (The __atribute((noinline))__ prevents the compiler from inlining the function). __atribute((noinline))__防止编译器内联函数)。 Then the generated assembly code is the same regardless whether the initialization line is present or not: 然后,无论是否存在初始化行,生成的汇编代码都是相同的:

-O1 with or without initialization -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

On the other hand, when compiled with -O0 the assembly code is different depending on whether the initialization line is present or not: 另一方面,当使用-O0进行编译时,汇编代码会根据是否存在初始化行而有所不同:

-O0 without initialization -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 with initialization -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

Notice that -O0 with initialization has four extra lines (marked above) than -O0 without initialization. 请注意,带初始化的-O0比没有初始化的-O0多了四行(上面标记)。 These extra lines initialize the two members to zero. 这些额外的行将两个成员初始化为零。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM