class dummy
{
union
{
templatefoo<randomclassa> * objecta;
templatefoo<randomclassb> * objectb;
};
~A()
{
delete this->objecta;
}
};
假设我在某个时候使用new分配了objectb,那么在objecta上调用delete会导致未定义的行为吗?
答案 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 [删除]]
在第一个替代(删除对象)中,如果要删除的对象的静态类型与其不同 动态类型,静态类型应该是要删除的对象的动态类型的基类 静态类型应具有虚拟析构函数或行为未定义。