C++ 工会可以';s的析构函数是平凡的吗?
给定以下代码:C++ 工会可以';s的析构函数是平凡的吗?,c++,language-lawyer,undefined-behavior,unions,C++,Language Lawyer,Undefined Behavior,Unions,给定以下代码: 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<Fo
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;
}
结构栏{
Bar(){}
~Bar(){}
};
结构FooBase{
//没有虚拟析构函数
};
结构Foo:FooBase{
Foo():bar{}{}
联合{
酒吧;
};
};
int main(){
FooBase*p=新的Foo;
静态_cast(p)->bar.~bar();
删除p;
}
我希望将Foo::bar
的生命周期与其所包含的Foo
分离据我所知,
删除p当且仅当Foo
的析构函数微不足道时,code>才是定义良好的。
由于Foo
只包含一个并集,并且不应该破坏它的bar
本身,所以看起来情况是这样的:非正式地说,析构函数什么也不做
但是这个代码实际上是根据标准定义的吗
首先,[expr.delete]
对我来说并不支持你的说法,“delete p;
是定义良好的,当且仅当Foo的析构函数是微不足道的”
在第一个备选方案(删除对象)中,如果要删除的对象的静态类型与其动态类型不同,则静态类型应为要删除的对象的动态类型的基类,并且静态类型应具有虚拟析构函数,或者行为未定义
因为静态类型是FooBase
,而动态类型是Foo
,所以我希望是UB
此外,(即使这不是UB),我认为Foo
的析构函数不是微不足道的
[班级工会]
类联合类是一个联合或具有匿名联合作为直接成员的类。类似于class X
的联合具有一组变量成员。如果X
是一个联合,则其变量成员是非静态数据成员;否则,其变量成员是属于X
的所有匿名联合的非静态数据成员
因此,Foo
是一个类似于并集的类,其中bar
(类型为bar
,具有非平凡的析构函数)是一个变量成员
[类别.dtor]
4) 如果类没有用户声明的析构函数,则析构函数将隐式声明为默认[…]
5) 类X的默认析构函数定义为已删除,如果
X
是一个类似于并集的类,它有一个带有非平凡析构函数[…]的变量成员
因此,我认为Foo
的隐式默认析构函数应该定义为deleted,并且必须由用户提供
(声明fooq;
并查看编译失败。)
如果析构函数不是用户提供的,并且
- […]对于其类中属于类类型(或其数组)的所有非静态数据成员,每个此类类都有一个平凡的析构函数
我希望该子句也能扩展到变量成员,因为它没有说“非变量数据成员”
可以在FooBase
中拥有一个虚拟析构函数,然后实现~Foo()
,而不包括bar.~bar()
可以预先销毁条
,而无需在~Foo()
中再次销毁
然而,我强烈建议不要这样做,因为在它超出范围之前,您必须以某种方式为每个静态或动态Foo
调用~bar
。1。)只有一个成员变量的未命名联合是奇怪的。2.)如果您不确定,则很可能是UB。我怀疑你的假设,delete p
在这里定义得很好。@knivil我怀疑它是否定义得很好;)啊,,,我想你会问一些其他奇怪的事情,比如Foo
s析构函数或分配给基类指针而不具有多态性。VS2015:警告C4624:“Foo”:析构函数被隐式定义为deletedIs,如果我通过基类指针销毁它,则使用Foo
的析构函数?@knivil:如果基类没有虚拟析构函数是UB。实现可以使用也可以不使用Foo
的析构函数。