成员初始化列表,没有参数

时间:2016-01-28 21:34:09

标签: c++ pointers initializer-list

在一个曾经使用过许多智能指针并且现在使用原始指针的大型框架中,我经常遇到这样的情况:

class A {
public:
        int* m;
        A() : m() {}
};

原因是因为int* m曾经是一个智能指针,所以初始化列表称为默认构造函数。既然int* m是一个原始指针,我不确定这是否等同于:

class A {
public:
        int* m;
        A() : m(nullptr) {}
};

如果没有明确的nullptr A::m仍然初始化为零?看看没有优化objdump -d会让它看起来像是,但我不确定。我认为答案是肯定的原因是objdump -d中的这一行(我发布了以下objdump -d的更多内容):

  400644:       48 c7 00 00 00 00 00    movq   $0x0,(%rax)

尝试查找未定义行为的小程序

class A {
public:
        int* m;
        A() : m(nullptr) {}
};

int main() {
        A buf[1000000];
        unsigned int count = 0;
        for (unsigned int i = 0; i < 1000000; ++i) {
                count += buf[i].m ? 1 : 0;
        }
        return count;
}

编译,执行和返回值

g++ -std=c++14 -O0 foo.cpp
./a.out; echo $?
0

来自objdump -d 的相关装配部分:

00000000004005b8 <main>:
  4005b8:       55                      push   %rbp
  4005b9:       48 89 e5                mov    %rsp,%rbp
  4005bc:       41 54                   push   %r12
  4005be:       53                      push   %rbx
  4005bf:       48 81 ec 10 12 7a 00    sub    $0x7a1210,%rsp
  4005c6:       48 8d 85 e0 ed 85 ff    lea    -0x7a1220(%rbp),%rax
  4005cd:       bb 3f 42 0f 00          mov    $0xf423f,%ebx
  4005d2:       49 89 c4                mov    %rax,%r12
  4005d5:       eb 10                   jmp    4005e7 <main+0x2f>
  4005d7:       4c 89 e7                mov    %r12,%rdi
  4005da:       e8 59 00 00 00          callq  400638 <_ZN1AC1Ev>
  4005df:       49 83 c4 08             add    $0x8,%r12
  4005e3:       48 83 eb 01             sub    $0x1,%rbx
  4005e7:       48 83 fb ff             cmp    $0xffffffffffffffff,%rbx
  4005eb:       75 ea                   jne    4005d7 <main+0x1f>
  4005ed:       c7 45 ec 00 00 00 00    movl   $0x0,-0x14(%rbp)
  4005f4:       c7 45 e8 00 00 00 00    movl   $0x0,-0x18(%rbp)
  4005fb:       eb 23                   jmp    400620 <main+0x68>
  4005fd:       8b 45 e8                mov    -0x18(%rbp),%eax
  400600:       48 8b 84 c5 e0 ed 85    mov    -0x7a1220(%rbp,%rax,8),%rax
  400607:       ff
  400608:       48 85 c0                test   %rax,%rax
  40060b:       74 07                   je     400614 <main+0x5c>
  40060d:       b8 01 00 00 00          mov    $0x1,%eax
  400612:       eb 05                   jmp    400619 <main+0x61>
  400614:       b8 00 00 00 00          mov    $0x0,%eax
  400619:       01 45 ec                add    %eax,-0x14(%rbp)
  40061c:       83 45 e8 01             addl   $0x1,-0x18(%rbp)
  400620:       81 7d e8 3f 42 0f 00    cmpl   $0xf423f,-0x18(%rbp)
  400627:       76 d4                   jbe    4005fd <main+0x45>
  400629:       8b 45 ec                mov    -0x14(%rbp),%eax
  40062c:       48 81 c4 10 12 7a 00    add    $0x7a1210,%rsp
  400633:       5b                      pop    %rbx
  400634:       41 5c                   pop    %r12
  400636:       5d                      pop    %rbp
  400637:       c3                      retq

0000000000400638 <_ZN1AC1Ev>:
  400638:       55                      push   %rbp
  400639:       48 89 e5                mov    %rsp,%rbp
  40063c:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
  400640:       48 8b 45 f8             mov    -0x8(%rbp),%rax
  400644:       48 c7 00 00 00 00 00    movq   $0x0,(%rax)
  40064b:       5d                      pop    %rbp
  40064c:       c3                      retq
  40064d:       0f 1f 00                nopl   (%rax)

1 个答案:

答案 0 :(得分:7)

()初始化程序代表C ++ 98中的 default-initialization 和C ++ 03及更高版本中的 value-initialization 。对于标量类型(包括指针),值初始化/默认初始化会导致零初始化

这意味着在您的情况下m()m(nullptr)将具有完全相同的效果:在两种情况下m都被初始化为空指针。在C ++中,从标准化时代开始就是这样。