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;
相关的反汇编。__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;
};
或非静态数据成员初始化项(大括号-or-equal-initializer)
class Foo {
public:
int a = 0,
*p = nullptr;
};
或保持Foo
不变,并初始化实例
Foo f{};
使用原始示例,我无法重现使用VS2013, 32位调试构建观察到的结果。得到的输出是
f: cccccccc cccccccc
b: cccccccc cccccccc
j: cccccccc cccccccc
EDIT:我能够重现b
被零初始化的行为。如果您启用/sdl
(安全开发生命周期检查)编译器开关(在配置属性-> C/c++ -> General下),就会发生这种情况。
来自交换机的MSDN文档:
当启用
/sdl
时,编译器生成在运行时执行这些检查的代码:
本;...
本;执行类成员初始化。在对象实例化时自动将所有类成员初始化为零(在构造函数运行之前)。这有助于防止使用与构造函数未显式初始化的类成员关联的未初始化数据。
这篇博文甚至提到了__autoclassinit
函数,尽管他列出的启发式方法与我们观察到的并不完全匹配,因为该功能的行为在VS2012和VS2013之间发生了变化。
同样毫无价值的是,编译器似乎不仅区分聚合(Foo
)和非聚合(其他两个),这有一定的意义,但是,由于一些真正奇怪的原因,它只会执行这种零初始化,如果您使用类键 class
,而不是struct
,在类定义中。
- C++成员初始化
- c++构造函数成员初始化:传递参数
- C++正确的指针成员初始化
- 将另一个类的对象传递到当前类C++的构造函数中(不是成员初始化)
- WinLamb 错误:成员初始化非法
- 使用其他成员初始化结构的成员?
- C++模板类静态成员初始化
- 解释了构造函数成员初始化列表
- 如何在成员初始化列表中声明共享指针
- C++入门5版:使用get成员初始化另一个与shared_ptr无关的对象
- C++11 默认类成员初始化与初始值设定项列表同时
- 调用非默认构造函数作为成员初始化
- C++模板成员初始化:用右值移动构造,但用左值移动引用
- 类成员初始化C++
- 在成员初始化列表中,我可以创建对列表中不在列表中的成员变量的引用
- C :(不重复)积分静态成员初始化(不仅是声明!),导致链接器错误,原因
- 如何调用成员初始化器列表中参考成员的构造函数
- C 构造函数采用成员初始化器
- 与其他静态const成员初始化静态常量成员
- 静态内联成员初始化顺序