含有挥发性结构的联盟

时间:2015-02-05 01:53:52

标签: c++ language-lawyer volatile unions c++03

这似乎与POD structs containing constant member类似,但有些相反。

#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;
}

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

$ g++ -std=c++03 a.cpp -o a_gcc
$ ./a_gcc
12

但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.

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;
}

..然后它会起作用。我想知道为什么clang ++对它们的处理方式不同。

1 个答案:

答案 0 :(得分:0)

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

  

[注意:如果有任何非静态数据成员   union的一个非平凡的默认构造函数(12.1),复制构造函数(12.8),移动构造函数(12.8),   复制赋值运算符(12.8),移动赋值运算符(12.8)或析构函数(12.4),对应的   union的成员函数必须是用户提供的,否则将隐式删除(8.4.3)union。 -end note]

在[class.copy],§12.8/ 25中,我们看到我们的union有一个非平凡的复制构造函数:

  

如果不是用户提供的,则类X的复制/移动赋值运算符是微不足道的,其参数类型列表是   相当于隐式声明的参数类型列表,如果...
   - [..]
   - 类X具有没有volatile限定类型的非静态数据成员

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

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