【问题标题】:AFAIK, the code below shouldn't compile, but it does in clang and GCC. What am I missing here?AFAIK,下面的代码不应该编译,但它可以在 clang 和 GCC 中编译。我在这里想念什么?
【发布时间】:2015-02-20 19:02:50
【问题描述】:

下面的代码显示了一个类似联合的类,它具有一个重要的默认构造函数(成员 y 使用 brace-or-equal-initializer 进行初始化),所以如果一个默认构造函数用于这样的类是默认的,应该根据 §12.1/5 第一个要点将其删除。也就是说,声明T t; 不应编译,因为union T 没有默认构造函数。但是clang和GCC中的code compiles and executes

#include <iostream>
union T
{
    int y{1};
    float x;
    char c;
    T() = default;
};

int main()
{
    T t;
    std::cout << t.y << '\n';
}

编辑

我上面的问题从一开始就错了,因为联合 T 不是 类似联合的类。我刚刚了解了 C++11 中的 §9.5/8,它说:

类似联合的类是联合或具有匿名联合的类 作为直接会员。类似联合的类 X 有一组变体成员。 如果 X 是联合,则其变体成员是非静态数据成员; 否则,它的变体成员是所有的非静态数据成员 作为 X 成员的匿名工会。

现在,考虑下面的 sn-p。它无法编译,因为联合的默认构造函数已被删除。但我仍然不知道 §12.1/5 中的哪个要点对这个结果负责。请注意,联合不是 类似联合的类,因此第 12.1/5 节中的第一个要点不适用。但这就是 clang 和 GCC 中的错误消息。见live example

#include <iostream>

union T{
    int y;
    struct A{ int i; A():i{1} {} } a;
};

int main()
{
    T t;
    std::cout << t.a.i << '\n';
}

【问题讨论】:

  • "一个默认构造函数被默认且未定义为已删除,在它被 od-rused 时隐式定义" 因为你的构造函数看起来是 odr-used,它不应该是有效代码吗?跨度>
  • 它也可以为 VS 2015 Preview 编译而没有问题。
  • 无法以任何方式实例化的联合的目的是什么?

标签: c++ c++11 language-lawyer


【解决方案1】:

子弹是

X 是一个类联合类,它有一个变体成员 默认构造函数

解析为

X 是一个类似联合的类,它具有(具有非平凡的变体成员 默认构造函数)

即,“具有重要的默认构造函数”适用于变体成员的类型,而不是 X

【讨论】:

  • 即便如此,y 的默认构造函数不是很重要吗?或者也许非平凡的概念不适用于内置类型?
  • @Ayrosa y 是一个int,它像所有原始类型一样没有构造函数。更不用说非平凡的构造函数了。定义 int y{1}; 中的 brace-or-equal-initializer {1} 不是 y 的构造函数,它用于初始化 union's 中的 y没有提供其他初始化程序时的构造函数。换句话说,那个{1}的存在意味着你的T() = default;T() : y{1} {}的效果是一样的。
  • @T.C.您介意对我上面的编辑发表评论吗?
  • @Ayrosa 被解析为“类似联合的类是(联合)或(具有匿名联合作为直接成员的类)”。联合是一个类似联合的类。
  • @T.C.我不敢相信我从一开始就没有看到这一点。无论如何谢谢 (+1)。
猜你喜欢
  • 2020-06-03
  • 2017-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多