gpt4 book ai didi

c++ - 为什么为 union 或类似 union 的类删除了默认的默认构造函数?

转载 作者:行者123 更新时间:2023-12-03 10:03:22 26 4
gpt4 key购买 nike

struct A{
A(){}
};
union C{
A a;
int b = 0;
};
int main(){
C c;
}

在上面的代码中, GCC and Clang两者都提示 union C 的默认构造函数定义为删除。
但是,相关规则说:

A defaulted default constructor for class X is defined as deleted if:

  • X is a union that has a variant member with a non-trivial default constructor and no variant member of X has a default member initializer,
  • X is a non-union class that has a variant member M with a non-trivial default constructor and no variant member of the anonymous union containing M has a default member initializer,


注意强调的措辞。在示例中,IIUC,因为变体成员 b具有默认成员初始值设定项,默认的默认构造函数不应定义为已删除。为什么这些编译器会将此代码报告为格式错误?
如果更改 C 的定义到
union C{
A a{};
int b;
};
那么所有 compilers可以编译这段代码。该行为暗示该规则实际上意味着:

X is a union that has a variant member with a non-trivial default constructor and no default member initializer is supplied for the variant member


这是编译器错误还是该规则的措辞含糊不清?

最佳答案

这是在 C++14 和 C++17 之间改变的,通过 CWG 2084 ,它添加了允许(任何) union 成员上的 NSDMI 恢复默认的默认构造函数的语言。
CWG 2084 随附的示例与您的示例略有不同:

struct S {
S();
};
union U {
S s{};
} u;
这里 NSDMI 位于非平凡成员上,而 C++17 采用的措辞允许任何成员上的 NSDMI 恢复默认的默认构造函数。这是因为,正如该 DR 中所写,

An NSDMI is basically syntactic sugar for a mem-initializer


即, int b = 0; 上的 NSDMI基本上相当于用内存初始化器和空体编写一个构造函数:
C() : b{/*but use copy-initialization*/ 0} {}
顺便说一句,确保 union 的最多一个变体成员具有 NSDMI 的规则在某种程度上隐藏在 class.union.anon 的子条款中。 :

4 - [...] At most one variant member of a union may have a default member initializer.


我的假设是 由于 gcc 和 Clang 已经允许上述 (非平凡联盟成员上的 NSDMI)他们没有意识到他们需要更改他们的实现以获得完整的 C++17 支持。
这是 discussed on the list std-discussion in 2016 ,举个和你很相似的例子:
struct S {
S();
};
union U {
S s;
int i = 1;
} u;
结论是 clang 和 gcc 在拒绝方面有缺陷,尽管当时有一个误导性的说明, amended其结果。
对于 Clang,错误是 https://bugs.llvm.org/show_bug.cgi?id=39686这让我们回到 Implicitly defined constructor deleted due to variant member, N3690/N4140 vs N4659/N4727 处的 SO .我找不到 gcc 的相应错误。
请注意 MSVC correctly accepts , 并初始化 c.b = 0 , 即 correct per dcl.init.aggr :

5 - [...] If the aggregate is a union and the initializer list is empty, then

  • 5.4 - if any variant member has a default member initializer, that member is initialized from its default member initializer; [...]

关于c++ - 为什么为 union 或类似 union 的类删除了默认的默认构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65404305/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com