在this answer中,Ryan直接调用虚拟析构函数。我已经在VS2010中测试了代码,它正确调用了所有析构函数(使用日志语句测试)。这样做真的有效吗?这种方法有哪些问题,缺陷甚至是好点?
我只能将它视为真正强制重置实际类型的一种方法,即使它们没有覆盖虚拟reset
函数,因为它们至少必须在它们的析构函数中清理。 / p>
另外,调用析构函数会带来什么样的副作用?在这样的析构函数调用之后使用该对象是不确定的行为?如果立即通过new (this) MyClass();
电话重新初始化该怎么办?
答案 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调用将只调用引用区域中的构造函数和析构函数,因此内存分配在对象生命周期中被有效地分解