为什么非平凡成员需要在同一类中为匿名联合定义构造函数

时间:2019-03-22 00:37:24

标签: c++ c++17 linker-errors unions

在以下代码(https://wandbox.org/permlink/j9tN0hQzINa3W7cl

#include <iostream>
#include <memory>

using std::cout;
using std::endl;

class A {
public:
    A() {
        cout << "A::A()" << endl;
    }
    ~A() {
        cout << "A::~A()" << endl;
    }
};

class B {
public:
    ~B() {}

    void set() {
        new (&a_) A{};
    }

    void destroy() {
        a_.~A();
    }

    union {
        A a_;
    };
    A a2_{}; // (1)
};

int main() {
    auto b = B{};
}

以上代码的不变之处在于,通过构造和破坏类型为B的实例,如果设置了变体中的元素,则有人将调用destroy()来破坏联合中的元素。

为什么(1)的存在要求在B中明确定义匿名联合的析构函数?按原样编译时,链接器会在此代码中引发错误

Undefined symbols for architecture x86_64:
  "B::'unnamed'::~()",

这是c中的错误吗?这段代码可以使用gcc(https://wandbox.org/permlink/QvdJNWyrtG8gf9EE)进行编译

1 个答案:

答案 0 :(得分:0)

我无法真正重现您描述的确切问题。用// (1)所做的行是否存在对我的任何测试中的编译器是否接受代码都没有影响。另外,我没有得到链接器错误,而是编译器错误,指出析构函数已定义为已删除。

Try it out here

话虽如此,这似乎是clang中的错误。基于[class.dtor]\9B的析构函数不应调用 variant成员的析构函数 a_