繁体   English   中英

C ++ 11 VS2013类POD成员初始化

[英]C++11 VS2013 class POD member initialization

我到处寻找对此的解释,但我很快就会出现。 我从VS2013 v120平台工具集中看到了这种行为,但是当我将工具集设置为v90(VS2008工具集)时,一切都未初始化。 我相信这是由于C ++ 11的一些变化,但它也可能是v120平台工具集的异常。

任何人都可以在C ++ / C ++ 11级别上解释这里发生了什么吗? 也就是说,为什么b归零? 为什么j也没有归零? (也就是为什么结构体的行为与类不同)

另外,我知道我输出数据的方式是未定义的行为,请忽略它。 这里发布的方式比调试器窗口更容易。 这是在32位运行,因此指针的大小与unsigned int相同。

请考虑以下代码:

#include <iostream>

class Foo {
public:
  int a,
      *p;
};

class Bar {
public:
  Bar(){}
  int a,
      *p;
};

struct Jar {
  Jar(){}
  int a,
      *p;
};

int main() {
  Foo f;
  Bar b;
  Jar j;
  std::cout << std::hex; // please excuse this undefined-behavior producing test code, it's more simple to show this than a debugger window on SO (this is on 32-bit)
  std::cout << "f: " << ((unsigned*)&f)[0] << ' ' << ((unsigned*)&f)[1] << std::endl;
  std::cout << "b: " << ((unsigned*)&b)[0] << ' ' << ((unsigned*)&b)[1] << std::endl;
  std::cout << "j: " << ((unsigned*)&j)[0] << ' ' << ((unsigned*)&j)[1] << std::endl;
  return 0;
}

这是输出:

f: cccccccc cccccccc  
b: 0 0  
j: cccccccc cccccccc

编辑:
这是我看到与Bar b;相关的反汇编Bar b; __autoclassinit2将内存归零。 它不是构造函数的一部分,而是在构造函数调用之前归零。

  Bar b;
00886598  push        8  
0088659A  lea         ecx,[b]  
0088659D  call        Bar::__autoclassinit2 (0881181h)  
008865A2  lea         ecx,[b]  
008865A5  call        Bar::Bar (0881109h)  

您的所有类型都包含内置类型的数据成员,因此除非您执行以下操作之一,否则它们都不会进行零初始化(以Foo为例):

初始化默认构造函数中的成员:

class Foo {
public:
  Foo() : a(), p() {}
  int a,
      *p;
};

或非静态数据成员初始值设定项( 括号或等于初始化程序

class Foo {
public:
  int a = 0,
      *p = nullptr;
};

或者保持Foo不变,并且值初始化实例

Foo f{};

使用原始示例,我无法使用VS2013,32位调试版本重现您观察到的结果。 我得到的输出是

f: cccccccc cccccccc
b: cccccccc cccccccc
j: cccccccc cccccccc

编辑:我能够重现b被零初始化的行为。 如果启用/sdl安全开发生命周期检查 )编译器开关(在配置属性 - > C / C ++ - >常规下),则会发生这种情况。

从交换机的MSDN文档

启用/sdl ,编译器会生成代码以在运行时执行这些检查:
- ...
- 执行类成员初始化。 在对象实例化时(在构造函数运行之前)自动将所有类成员初始化为零 这有助于防止使用与构造函数未显式初始化的类成员关联的未初始化数据。

这篇博文甚至提到了__autoclassinit函数,尽管他列出的启发式方法并不完全符合我们观察的内容,因为此功能的行为在VS2012和VS2013 之间发生了变化。

同样值得一提的是,编译器似乎不仅区分聚合( Foo )和非聚合(其他两个),这是有道理的,但是,出于一些真正奇怪的原因,它只会执行这种零初始化,如果你在类定义中使用class-key class ,而不是struct

暂无
暂无

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

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