直接调用(虚拟)析构函数是否有效?

时间:2011-05-17 19:30:28

标签: c++ virtual-destructor self-destruction

this answer中,Ryan直接调用虚拟析构函数。我已经在VS2010中测试了代码,它正确调用了所有析构函数(使用日志语句测试)。这样做真的有效吗?这种方法有哪些问题,缺陷甚至是好点?

我只能将它视为真正强制重置实际类型的一种方法,即使它们没有覆盖虚拟reset函数,因为它们至少必须在它们的析构函数中清理。 / p>

另外,调用析构函数会带来什么样的副作用?在这样的析构函数调用之后使用该对象是不确定的行为?如果立即通过new (this) MyClass();电话重新初始化该怎么办?

3 个答案:

答案 0 :(得分:4)

手动调用析构函数是完全有效的,无论它是否是虚拟的。你只想确保每次构造函数调用只调用一次。

Is it undefined behaviour to use the object after such a destructor call? 

What if one immediatly reinitializes it with a new (this) MyClass(); call?

仍然可怕地未定义。

除非必须手动放置对象,否则不要手动破坏对象,例如与放置新的或一些等价物,绝对不会重新初始化这样的被破坏的对象,并希望避免UB。像std::vector这样的类非常明确地访问被破坏的对象UB,即使你在它的位置创建一个新元素,它仍然是UB。

答案 1 :(得分:1)

涉及一个且仅一个构造的有效使用的示例:

typedef boost::aligned_storage<
    sizeof(T), boost::alignement_of<T>::value>::type arena_type;
arena_type arena;
T* p = new (&arena) T();
p->~T();
// Don't touch p now

这在以下情况下非常有用:实现变体类型(警告:例外安全性作为练习留给读者)。 C ++ 0x不受限制的联合将具有类类型的类似用途。

请注意,对于类类型,如果您调用析构函数,则上面将是UB。

答案 2 :(得分:0)

只要您在预先分配的POD内存块之上调用 placement new ,它就完全有效,可以解除调用任何析构函数,无论是否虚拟化。

placement new和explicit deallocator调用将只调用引用区域中的构造函数和析构函数,因此内存分配在对象生命周期中被有效地分解