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

Thr*_*r57 4 c++ c++14

考虑这个例子:

#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?");
}
Run Code Online (Sandbox Code Playgroud)

如果我理解正确,根据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开发。

M.M*_*M.M 5

首先:对象b.a.a, b.a.b, b.a.c,b.a.d保证为零初始化。哪个 forfloat被初始化为 if = 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% 精确,但float为此目的,零初始化的 IMO应该算作“零值”。