含有挥发性结构的联盟

qbt*_*937 6 c++ volatile unions language-lawyer c++03

这似乎与包含常量成员的POD结构类似,但有点相反.

#include <iostream>

struct A
{
    int a;
};

union U
{
    volatile A a;
    long b;
};

int main()
{
    U u1;
    U u2;

    u1.a.a = 12;
    u2 = u1;
    std::cout << u2.a.a << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

g ++ 4.8.3编译此代码时没有错误,并且运行正常:

$ g++ -std=c++03 a.cpp -o a_gcc
$ ./a_gcc
12
Run Code Online (Sandbox Code Playgroud)

但是clang ++ 3.5.1会产生错误(我手动包装错误消息以防止代码框滚动):

$ clang++ -std=c++03 a.cpp -o a_clang
a.cpp:8:7: error: member function 'operator=' not viable: 'this'
argument has type 'volatile A', but function is not marked volatile
union U
      ^
a.cpp:3:8: note: 'operator=' declared here
struct A
       ^
a.cpp:20:5: note: implicit copy assignment operator for 'U' first
required here
        u2 = u1;
        ^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

C++ 03是否允许程序复制 - 分配包含volatile结构的联合?我在C++ 03标准中找不到任何定义联合的默认复制构造函数的东西.

我想知道哪个编译器是正确的,或者标准在那一点上是不清楚的.

编辑:我发现如果我使用复制构造而不是复制赋值,clang ++和g ++都会编译程序而不会出错.具体来说,如果我改为main:

int main()
{
    U u1;

    u1.a.a = 12;
    U u2 = u1;
    std::cout << u2.a.a << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

..然后它会工作.我想知道为什么clang ++对它们的区别对待.

Bar*_*rry 0

在C++11中,union的复制构造函数可以被删除。我们从 N4140 中的 [class.union], \xc2\xa79.5 中的注释中看到这一点:

\n\n
\n

[注意:如果联合体的任何非静态数据成员\n 具有重要的默认构造函数 (12.1)、复制构造函数 (12.8)、移动构造函数 (12.8)、\n 复制赋值运算符 (12.8)、移动赋值运算符(12.8) 或析构函数 (12.4),联合的相应成员函数必须是用户提供的,否则它将被隐式删除 (8.4.3) 联合。\xe2\x80\x94结束注]

\n
\n\n

在 [class.copy], \xc2\xa712.8/25 中,我们看到我们的union有一个不平凡的复制构造函数:

\n\n
\n

如果类 X 的复制/移动赋值运算符不是用户提供的,则它是微不足道的,其参数类型列表\n 等效于隐式声明的参数类型列表,并且如果 ...
\n \xe2 \x80\x94 [ .. ]
\n \xe2\x80\x94 类 X 没有volatile 限定类型的非静态数据成员,并且

\n
\n\n

但 [class.copy] 中的该特定行只是由于 Is a volatile-qualified type确实是 POD?的结果而添加的。在此之前,这样的类仍被认为具有简单的复制构造函数。

\n\n

所以我的理解是,在 C++03 中,没有任何迹象表明应删除 union 的复制构造函数,而在 C++11 中,有一些迹象表明这一点,但它是非规范的。

\n