c++ - 没有构造函数的 C++ 零初始化
问题描述
我不明白对于具有其成员默认值的结构的零初始化会发生什么。
如果我有这些结构:
struct A {
int *a;
int b;
};
struct B {
int *a;
int b;
B() : b(3) {}
};
struct C {
int *a;
int b = 3;
};
我们可以毫无疑问地说:
A a;
使所有字段未初始化A a{};
是 {nullptr, 0}B b;
并且B b{};
都是 {garbage, 3} (构造函数被调用)
现在还不清楚当我执行以下操作时会发生什么,以下是使用 gcc 的结果:
C c; // {garbage, 3}
C c{}; // {nullptr, 3}
问题是:如果我明确地构造对象,是否保证C c{};
初始化C::a
为nullptr
,换句话说,默认成员C
仍然为零会初始化其他成员C c{};
吗?
因为如果我有一个与C
(如 in B
)执行相同操作的构造函数,则不会发生这种情况,因此其他成员不是零初始化的,但为什么呢?B
和 和有什么不一样C
?
解决方案
从 C++14 开始,C
是一个聚合(如A
),并且C c{}
语法执行聚合初始化。这部分包括:
[dcl.init.aggr]/8如果列表中的初始化子句少于非联合聚合中的元素,则每个未显式初始化的元素按如下方式初始化:
(8.1) — 如果元素具有默认成员初始化程序(12.2),元素从该初始化程序初始化。
(8.2) — 否则,如果元素不是引用,则从空的初始化列表 (11.6.4) 复制初始化该元素。
(8.3) — 否则,程序格式错误。
所以C c{};
等价于C c{{}, 3};
。用空列表初始化int*
成员会导致它被零初始化。
在 C++11 中,C
is 不是聚合(具有默认成员初始化程序被取消资格),并C c{};
调用隐式定义的构造函数,使c.a
成员未初始化。
在标准的所有版本中,B
由于用户定义的构造函数,不是聚合。B b{};
调用该构造函数,该构造函数显式初始化b
成员并选择保持a
未初始化状态。
推荐阅读
- html - jQuery / 元素在加载时自动隐藏
- java - 如何在android的圆形cardview中弯曲一小部分以显示底部的在线状态图标
- assembly - C 代码到 DWORD PTR a[rip] 的汇编含义
- asp.net-mvc - 使用 HttpClient 在 ASP.NET MVC 中使用 ASP.NET Web API REST 服务
- python - 获取熊猫系列的列
- python - cx_Oracle 和 Lambda 层错误 - aws lambda 找不到 64 位 oracle 客户端库
- javascript - 为什么我不能初始化导入的属性而不先将其分配给变量?
- php - 无法通过 PHPMailer 验证 Google 帐户
- php - WooCommerce 更改订单行总数
- c++ - 使用 FFT 从音频中过滤 hit-hat 节拍