在指针联合中的任何成员上使用delete

时间:2015-09-19 00:54:50

标签: c++ unions

class dummy
{
    union
    {
        templatefoo<randomclassa> * objecta;
        templatefoo<randomclassb> * objectb;
    };
    ~A()
    {
        delete this->objecta;
    }
};

假设我在某个时候使用new分配了objectb,那么在objecta上调用delete会导致未定义的行为吗?

2 个答案:

答案 0 :(得分:3)

是。读取上次分配的成员以外的union成员将调用未定义的行为。

即使这不是问题,在“错误类型”的指针上调用delete也会调用UB。

解决这个问题的最简单方法是模板dummy本身,如果您要使用的类型在编译时已知或只存储两个指针,将未使用的一个设置为nullptr然后在析构函数中只有delete两个。

答案 1 :(得分:2)

是的,当然。在delete上调用objecta将导致调用第一个类型的析构函数,此时应调用第二个类型。

如果你想要这样的东西,你应该使用虚拟基类。上面没有做任何动态调度。

编辑:

这是另一种看待它的方式:

即使是最乐观的解释,你也许希望这样做,如果你已经完成了

templatefoo<B> * objectb;
objectb = reinterpret_cast<templatefoo<B>*>(new templatefoo<A>());
delete objectb;

但即使这已经是UB,除非在该模板中发生了一些非常不寻常的事情......

编辑:

这是标准中的一个特定点,不允许这样做:

  

[C ++ 11标准,5.3.5.3 [删除]]
  在第一个替代(删除对象)中,如果要删除的对象的静态类型与其不同   动态类型,静态类型应该是要删除的对象的动态类型的基类   静态类型应具有虚拟析构函数或行为未定义。