联合的析构函数可以是微不足道的吗?
Can an union's destructor be trivial?
给定以下代码:
struct Bar {
Bar() { }
~Bar() { }
};
struct FooBase {
// No virtual destructor
};
struct Foo : FooBase {
Foo() : bar{} { }
union {
Bar bar;
};
};
int main() {
FooBase *p = new Foo;
static_cast<Foo *>(p)->bar.~Bar();
delete p;
}
我希望将 Foo::bar
的生命周期与其封闭的 Foo
分开。
据我所知,delete p;
是明确定义的当且仅当 Foo
的析构函数是微不足道的。
由于 Foo
只包含一个联合,并且不应该破坏它的 bar
本身,看起来是这样的:非正式地说,析构函数什么都不做。
但是这个代码实际上是按照标准定义好的吗?
首先,[expr.delete]
对我来说不支持你的说法“delete p;
是明确定义的当且仅当 Foo 的析构函数是微不足道的".
In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined.
由于静态类型是 FooBase
而动态类型是 Foo
,我希望它是 UB。
此外,(即使这不是 UB)我认为 Foo
的析构函数不是微不足道的。
[class.union]
A union-like class is a union or a class that has an anonymous union as a direct member. A union-like class X
has a set of variant members. If X
is a union its variant members are the non-static data members; otherwise, its variant members are the non-static data members of all anonymous unions that are members of X
.
因此 Foo
是一个类似联合的 class,其中 bar
(类型 Bar
具有非平凡的析构函数)是变体成员。
[class.dtor]
4) If a class has no user-declared destructor, a destructor is implicitly declared as defaulted [...].
5) A defaulted destructor for a class X
is defined as deleted if
X
is a union-like class that has a variant member with a non-trivial destructor [...].
因此,我认为Foo
的隐式默认析构函数应该定义为已删除并且必须由用户提供。
(声明Foo q;
并看到编译失败。)
A destructor is trivial if it is not user-provided and if
- [...] for all of the non-static data members of its class that are of class type (or array thereof), each such class has a trivial destructor.
我希望该条款也扩展到变体成员,因为它没有说 "non-variant data members"。
你 可以 在 FooBase
中有一个虚拟析构函数,然后实现 ~Foo()
而不包括 bar.~bar();
可以销毁 bar
提前,而不会在 ~Foo()
.
中再次被破坏
但是我强烈反对它,因为在它超出范围之前你必须以某种方式为每个静态或动态 Foo
调用 ~bar
。
给定以下代码:
struct Bar {
Bar() { }
~Bar() { }
};
struct FooBase {
// No virtual destructor
};
struct Foo : FooBase {
Foo() : bar{} { }
union {
Bar bar;
};
};
int main() {
FooBase *p = new Foo;
static_cast<Foo *>(p)->bar.~Bar();
delete p;
}
我希望将 Foo::bar
的生命周期与其封闭的 Foo
分开。
据我所知,delete p;
是明确定义的当且仅当 Foo
的析构函数是微不足道的。
由于 Foo
只包含一个联合,并且不应该破坏它的 bar
本身,看起来是这样的:非正式地说,析构函数什么都不做。
但是这个代码实际上是按照标准定义好的吗?
首先,[expr.delete]
对我来说不支持你的说法“delete p;
是明确定义的当且仅当 Foo 的析构函数是微不足道的".
In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined.
由于静态类型是 FooBase
而动态类型是 Foo
,我希望它是 UB。
此外,(即使这不是 UB)我认为 Foo
的析构函数不是微不足道的。
[class.union]
A union-like class is a union or a class that has an anonymous union as a direct member. A union-like
class X
has a set of variant members. IfX
is a union its variant members are the non-static data members; otherwise, its variant members are the non-static data members of all anonymous unions that are members ofX
.
因此 Foo
是一个类似联合的 class,其中 bar
(类型 Bar
具有非平凡的析构函数)是变体成员。
[class.dtor]
4) If a class has no user-declared destructor, a destructor is implicitly declared as defaulted [...].
5) A defaulted destructor for a
class X
is defined as deleted if
X
is a union-like class that has a variant member with a non-trivial destructor [...].
因此,我认为Foo
的隐式默认析构函数应该定义为已删除并且必须由用户提供。
(声明Foo q;
并看到编译失败。)
A destructor is trivial if it is not user-provided and if
- [...] for all of the non-static data members of its class that are of class type (or array thereof), each such class has a trivial destructor.
我希望该条款也扩展到变体成员,因为它没有说 "non-variant data members"。
你 可以 在 FooBase
中有一个虚拟析构函数,然后实现 ~Foo()
而不包括 bar.~bar();
可以销毁 bar
提前,而不会在 ~Foo()
.
但是我强烈反对它,因为在它超出范围之前你必须以某种方式为每个静态或动态 Foo
调用 ~bar
。