与同事讨论后我产生了一些疑问......
如标题所问,什么时候可以假设内置类型将被初始化为 0 而不是未知值?
C++ 标准之间的规则是否有所不同?
完整规则位于 [dcl.init] (C++11) 中。总结一下:当声明中没有提供初始化程序时,该实体被称为“默认初始化”。对于类类型,这意味着调用默认构造函数。对于非类类型,这意味着 不执行初始化。 但是,[dcl.init] §9 指出:“在程序启动时,在发生任何其他初始化之前,静态存储持续时间的每个对象都将被初始化为零。”
这意味着非类类型的静态持续时间变量(例如命名空间范围变量)是零初始化的。其他非类类型的对象(例如局部变量)
未初始化。
,我将尝试提供代码片段来让编译器为您初始化成员:
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
}
和C++03标准:
3.6.2 非本地对象的初始化,§1:
具有静态存储持续时间(3.7.1)的对象应在进行任何其他初始化之前进行零初始化(8.5)。3.7.1 静态存储持续时间,§1
:
所有既没有动态存储持续时间也不是本地的对象都具有静态存储持续时间。3.7.1 静态存储持续时间,§3
:
关键字8.5 初始化器,§6static
可用于声明具有静态存储期限的局部变量。
还有
:
每个静态存储持续时间的对象都应在程序启动时进行零初始化,然后再进行任何其他初始化。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
根据经验,初始化变量,因为这样编程更安全。
编辑:正如 Luchian Grigore 所指出的,全局/命名空间范围变量是一个例外。由于这种初始化,它们通常也无法处理未初始化的变量检查。