c++ - Zero initialization of nested struct - compiler bug?
问题描述
Consider this example:
#include <vector>
#include <stdexcept>
struct A
{
float a;
float b;
float c;
float d;
};
struct B
{
A a;
std::vector<int> b;
};
int main() {
B b{};
if (b.a.a || b.a.b || b.a.c || b.a.d) throw std::runtime_error("Compiler bug?");
}
If I understand correctly, according to https://en.cppreference.com/w/cpp/language/zero_initialization, it cannot throw because zero initialization should be performed for B::a as it should for "members of value-initialized class types that have no constructors".
If it throws, is it a compiler bug or am I missing something?
[edit]
Here with clang 10 and optimization enabled it just does "mov eax, 2" and "ret" (meaning the condition is false): https://godbolt.org/z/CXrc3G
But if I remove the braces, it does "mov eax, 1" and "ret" (meaning the condition is true). But here I think it can return whatever it want because it's just UB. https://godbolt.org/z/tBvLzZ
So it seems clang thinks that with braces zero initialization must be performed.
Edit: I submitted a bug on intel's website: https://community.intel.com/t5/Intel-C-Compiler/Aggregate-initialization-bug-with-nested-struct/td-p/1178228
An intel person replied "I've reported this issue to our Developer." Poor developer, single-handedly supporting all icc development.
解决方案
首先:对象b.a.a
, b.a.b
, b.a.c
,b.a.d
保证为零初始化。其中 forfloat
被初始化为= 0;
(不一定是所有位为零的表示)。
B b{};
在某些情况下仅转换为零初始化(cppreference 页面有点误导)。
在 C++14 中:因为B
是一个聚合,所以这是聚合初始化,每个成员都被初始化为一个空列表。所以A a;
被初始化为 if A a{};
。也是一个聚合,所以它的A
每个元素都被初始化为一个空列表,对于内置类型是零初始化。
在 C++11 中,措辞不同(从空列表对聚合类进行列表初始化实际上并不认为是聚合初始化),但结果是相同的。
在 C++03 中,B b{}
; 是一个语法错误,但B b = {};
被允许,并且结果也将有问题的浮点数初始化为零。
在 C++98 中,规则不同,长话短说,B b = {};
将调用默认构造函数,A
其值未初始化。我们喜欢假装 C++98 初始化从未存在,但一些编译器甚至在 2010 年代仍坚持这些规则。
有了这个,可能会有一些关于是否保证零初始化的浮点数作为运算符的争论false
,||
请参阅将浮点数与零进行比较。
该标准说“将零值、空指针值或空成员指针值转换为false
”。这不是 100% 精确的,但 IMO 零初始化float
应该算作“零值”。
推荐阅读
- sql - 如何仅从包含 Oracle SQL 中特定字符串的列中选择和别名数据
- python - 使用 html 标签而不是正则表达式来抓取房价
- c# - CS7036 错误消息在 asp.net core razor pages C# 的 Pages 文件夹中使用 Partial.cshtml 文件
- python - 原始字符串不将反斜杠视为文字字符吗?
- javascript - 在启动时从 Hapi js 服务器使用外部 API 不返回承诺
- github - 如何将文件夹中的图片添加到我的 github 自述文件中?
- python - 如何获取屏幕上显示的pdf页面的位置?
- wagtail - 列 clean_name 不存在(Wagtail 2.10)
- entity-framework - 无法在 docker 容器中以非 root 身份运行 EF
- python-3.x - 子进程 Hexdump 命令返回错误格式错误