嵌套结构编译器错误的零初始化

Zero initialization of nested struct - compiler bug?

本文关键字:初始化 错误 结构 编译器 嵌套      更新时间:2024-05-09

考虑这个例子:

#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?");
}

如果我理解正确,根据https://en.cppreference.com/w/cpp/language/zero_initialization,它不能抛出,因为应该对B::a执行零初始化,就像对"执行零初始化一样;没有构造函数的值初始化类类型的成员";。

如果它抛出,是编译器错误还是我遗漏了什么?

[编辑]

在clang 10和优化启用的情况下;mov eax,2〃;以及";ret";(表示条件为假(:https://godbolt.org/z/CXrc3G

但如果我去掉牙套,它会";mov eax,1〃;以及";ret";(意味着条件成立(。但在这里,我认为它可以返回任何它想要的,因为它只是UB。https://godbolt.org/z/tBvLzZ

所以clang似乎认为使用大括号必须执行零初始化。

编辑:我在英特尔的网站上提交了一个错误:https://community.intel.com/t5/Intel-C-Compiler/Aggregate-initialization-bug-with-nested-struct/td-p/1178228

一位情报人员回答说:;我已经向我们的开发人员报告了这个问题"糟糕的开发人员,独自支持所有icc的开发。

首先:保证对象b.a.ab.a.bb.a.cb.a.d初始化为零。其对于CCD_ 5被初始化为好像通过CCD_。

B b{};仅在某些情况下转换为零初始化(cpprreference页面有点误导(。

在C++14中:由于B是一个聚合,所以这是聚合初始化,每个成员都被初始化为空列表。所以A a;被初始化为A a{};A也是一个聚合,因此它的每个元素都被初始化为一个空列表,对于内置类型来说,这是零初始化。

在C++11中,措辞不同(从空列表对聚合类进行列表初始化实际上并不被视为聚合初始化(,但结果是相同的。

在C++03中,B b{};是一个语法错误,但B b = {};是允许的,并且对有问题的浮点值也进行了零初始化。

在C++98中,规则是不同的,长话短说,B b = {};将调用A的默认构造函数,这将使值未初始化。我们喜欢假装C++98初始化从未存在过,但一些编译器甚至在2010年代都坚持这些规则。


如果不这样做,可能会有一些关于零初始化浮点是否保证充当||运算符的false的争论,请参阅将浮点数与零进行比较。

该标准规定"零值、空指针值或空成员指针值转换为false"。这不是100%精确的,但为了这个目的,初始化为零的float应该算作"零值"。