请考虑以下代码:
#include <iostream>
struct A{ // with implicit default constructor
int number;
};
struct B{
int number;
B(){}; // user-provided default constructor
};
int main()
{
A aa = {};
B bb = {};
std::cout << "aa.number: " << aa.number << std::endl;
std::cout << "bb.number: " << bb.number << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
在线运行代码会 产生以下输出:
aa.number: 0
bb.number: 19715
Run Code Online (Sandbox Code Playgroud)
为什么 bb.number 未初始化?我认为使用 ={} 可以保证零初始化?
Nat*_*ica 10
我认为使用 ={} 可以保证零初始化?
仅当类型“正确”时才是正确的,而事实B并非如此。 B bb = {};将默认构造 aB并且您的默认构造函数 ,B(){};不会初始化,number因此无论如何number都不会被初始化,因为这就是您的默认构造函数的工作方式。如果你有一个“正确”的构造函数,比如
B() : number(0) {};
// or use
int number = 0;
B(){};
Run Code Online (Sandbox Code Playgroud)
然后你会得到number默认构造时的零初始化。
情况并非如此,A因为A是一个聚合,并且如果使用了空的支撑初始化列表( 的技术名称){},则它们具有某些保证,例如零初始化。
A是一个聚合类型,因为它没有任何用户提供的构造函数(并满足一些其他要求)。
因此A aa = {};也不能叫隐式生成的默认构造函数。相反,使用花括号括起来的初始化列表进行初始化执行聚合初始化,这对于空列表意味着成员如同由{}初始化程序初始化一样,这反过来意味着对于标量类型的成员,例如int它将被初始化为零。
B是不是一个聚合类型,因为它确实有一个用户提供的构造函数。
因此B bb = {};不能进行聚合初始化,而是调用默认构造函数。默认构造函数(在A或 中B)没有为成员指定初始值设定项,因此该成员是default-initialized,对于基本类型,例如int,这意味着它不会被设置为任何值。它的价值将保持不确定。
访问您的程序所做的不确定值会导致未定义的行为。
如果您自己声明一个构造函数,则该构造函数有责任适当地初始化所有成员。该规则= {}或{}永远只能初始化假设用户提供的默认构造函数,如果存在的话,下保持做正确的事在这个意义上,它提供了合理的初始化它的所有成员,它并不一定意味着零初始化一定。
| 归档时间: |
|
| 查看次数: |
148 次 |
| 最近记录: |