【发布时间】:2016-04-30 05:05:42
【问题描述】:
来自 C++ Primer (13.1.6):
编译器不会让我们 定义变量或创建具有已删除析构函数的类型的临时变量。 此外,我们不能定义具有成员的类的变量或临时对象 其类型具有已删除的析构函数。 如果成员具有已删除的析构函数,则 成员不能被销毁。如果一个成员不能被销毁,则该对象作为一个整体 无法销毁。
这似乎是真的:
class B{
public:
B() { }
~B() = delete;
};
class A{
public:
A() {}
~A() {}
B b;
};
int main(){
//B b; //error
A a; //error
}
带来关于B 的已删除析构函数的各种错误。这一定是因为析构函数,即使是显式析构函数,隐式调用类成员的析构函数,如 N3337 的 (12.4/8) 中指出的那样:
在执行析构函数的主体并销毁主体内分配的所有自动对象后, 类 X 的析构函数调用 X 的直接非变体非静态数据成员的析构函数,即析构函数 对于 X 的直接基类,如果 X 是最派生类 (12.6.2) 的类型,则其析构函数调用 X 的虚拟基类的析构函数。
我现在很好奇为什么以下方法有效:
#include <string>
class A{
public:
A() { }
union {
std::string test;
};
~A() { }
};
int main(){
A b;
}
鉴于此,从 N3337 的 9.5/2 开始:
如果联合的任何非静态数据成员具有非平凡的默认值 构造函数(12.1)、拷贝构造函数(12.8)、移动构造函数(12.8)、拷贝赋值运算符(12.8)、移动赋值运算符(12.8)或析构函数(12.4),联合的对应成员函数必须是 用户提供,否则会为联合隐式删除 (8.4.3)。
我的类A 有一个匿名联合对象,该对象又具有一个string 数据成员,它当然定义了自己的析构函数。因此,从上面看,联合必须有一个已删除的析构函数!但是我上面的引述说不可能创建A 类型的对象,因为它有一个带有已删除析构函数的成员。如果我注释掉~A(){},那么确实会出现错误,但由于某种原因,我的明确定义是可以的。当我的显式定义试图隐式销毁联合对象时会发生什么?
【问题讨论】:
标签: c++ c++11 destructor unions