C++结构体中的字符数组以不寻常的方式初始化为零

6

我遇到了一段不常见的C++初始化代码,它与以下内容相当好地配合使用...

struct sfoobar { char bar[10]; char foo[10]; };
...
sfoobar x { 0 };

这种方法是否可接受来将这些char数组初始化为零?

3
“非常规的”实际上很常见。 - SwiftMango
是的,这是一个可接受的方法。 - Sid S
2
sfoobar x { }; 是一个推荐的模式,因为即使第一个成员不正确初始化为 0,它仍然有效。与 struct qux { std::string bar; char foo[10]; }; 进行比较,然后 qux x{0}; 就会导致未定义的行为。 - M.M
@M.M 你能详细解释一下为什么 qux x{0}; 会导致未定义行为吗?为什么不会简单地生成编译错误呢?(如果 std::string 不支持这样的初始化。) - 303
@303 std::string有一个接受char const *的构造函数(如果传递了空指针,则为UB),并且0可以隐式转换为空指针。 - M.M
1个回答

8
这在C++中是有效的。因为sfoobar x { 0 };的效果会将x.barx.foo的所有元素都初始化为0
根据聚合初始化的规则,嵌套初始化列表的大括号可以省略,

嵌套初始化列表周围的大括号可以省略,在这种情况下,使用尽可能多的初始化子句来初始化相应子聚合的每个成员或元素,并使用后续初始化子句来初始化对象的以下成员。

那么sfoobar x { 0 };意味着将x.bar的第一个元素初始化为0,并且

如果初始化子句的数量少于成员数和基类(自C++17起)或初始化列表完全为空,则剩余的成员和基类(自C++17起)通过其默认初始化程序进行初始化,如果在类定义中提供了该程序,则按照通常的列表初始化规则进行(对于非类类型和具有默认构造函数的非聚合类执行值初始化,对于聚合执行聚合初始化)

所以所有剩余的元素,包括x.bar的第二到第十个元素和x.foo的所有元素也将被值初始化为0

问题是,对于字符数组,value initializationzero initialization是否相同? - Joseph D.
1
@codekaizer 是的,对于非类类型,值初始化会导致零初始化。对于这种情况,流程将是在char数组上进行聚合初始化,然后在元素(即char)上进行值初始化,最后在元素(即char)上进行零初始化 - songyuanyao
如果我写sfoobar x { 1 };,那么x.bar的第一个元素将被初始化为1,而x.barx.foo的所有其他元素都将被初始化为零?如果我只写sfoobar x,那么x.barx.foo的元素值是未确定的? - M. Winter
@M.Winter 是的,完全正确。 - songyuanyao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接