在什么情况下对象会被零初始化而不是默认初始化?

问题描述 投票:0回答:4

与同事讨论后我产生了一些疑问......

如标题所问,什么时候可以假设内置类型将被初始化为 0 而不是未知值?

C++ 标准之间的规则是否有所不同?

c++ initialization language-lawyer built-in-types
4个回答
7
投票

完整规则位于 [dcl.init] (C++11) 中。总结一下:当声明中没有提供初始化程序时,该实体被称为“默认初始化”。对于类类型,这意味着调用默认构造函数。对于非类类型,这意味着 不执行初始化。 但是,[dcl.init] §9 指出:“在程序启动时,在发生任何其他初始化之前,静态存储持续时间的每个对象都将被初始化为零。”

这意味着非类类型的静态持续时间变量(例如命名空间范围变量)是零初始化的。其他非类类型的对象(例如局部变量)

初始化。


3
投票
只有具有静态存储的 POD 对象才会自动初始化为 0

,我将尝试提供代码片段来让编译器为您初始化成员: struct POD { int a; double b; //... }; // namespace level: POD p; void f() { POD n1; // uninitialized POD p1 = {}; POD p2 = POD(); POD* n2 = new POD; // uninitialized POD* pp1 = new POD(); delete n2; delete pp1; }

在上面的示例中,只有那些标记为“未初始化”的不会被初始化。请注意,这是相对于标准要求的,您的里程会因不同的编译器而异。特别是,在某些情况下,VS 在 
T t = T();

T* p = new T()'
方面存在一些问题(IIRC,当类型
T
不是 POD,但没有用户提供的默认构造函数时,编译器将无法初始化 POD 子对象:

struct T { std::string s; int i; }; void f() { T t = T(); // t.i == 0 according to the standard }



3
投票

根据

C++98

C++03标准:

3.6.2 非本地对象的初始化,§1

:

具有静态存储持续时间(3.7.1)的对象应在进行任何其他初始化之前进行零初始化(8.5)。

3.7.1 静态存储持续时间,§1

:

所有既没有动态存储持续时间也不是本地的对象都具有
静态存储持续时间。

3.7.1 静态存储持续时间,§3

:

关键字
static

可用于声明具有静态存储期限的局部变量。



还有
8.5 初始化器,§6

每个静态存储持续时间的对象都应在程序启动时进行零初始化,然后再进行任何其他初始化。

这在两个标准中都是相同的。唯一的区别在于
C++98 的 8.5 §6

的表述:

任何静态存储期的对象所占用的内存都应该被零初始化 在程序启动时,在进行任何其他初始化之前。

示例:

这里是示例,其中

x

y
和 具有静态存储持续时间,因此标准保证它们在程序启动时都将被零初始化。请注意,还有以相同方式声明的 POD 对象
a
b
,因此具有静态存储持续时间,这意味着它们的成员(
i
d
)也将被零初始化:

struct POD { int i; double d; }; int x; POD a; int foo() { static int y; return y; } int main() { static POD b; std::cout << "x = " << x << std::endl; std::cout << "y = " << foo() << std::endl; std::cout << "a.i = " << a.i << std::endl; std::cout << "b.d = " << b.d << std::endl; }

这个例子的输出当然是:

x = 0 y = 0 a.i = 0 b.d = 0



-2
投票

根据经验,初始化变量,因为这样编程更安全。

编辑:正如 Luchian Grigore 所指出的,全局/命名空间范围变量是一个例外。由于这种初始化,它们通常也无法处理未初始化的变量检查。

© www.soinside.com 2019 - 2024. All rights reserved.