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
分离
据我所知,
删除pFoo
的析构函数微不足道时,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
的析构函数。