7

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

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

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

4

3 回答 3

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?

仍然可怕地不确定。

不要手动破坏一个对象,除非你必须手动放置它,例如使用placement new 或一些等效的,并且绝对不要像那样重新初始化一个被破坏的对象并希望避免UB。像std::vector非常显式地访问被破坏的对象 UB 的类,即使你在它的位置创建一个新元素,它仍然是 UB。

于 2011-05-17T19:31:20.827 回答
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

于 2011-05-17T19:49:18.167 回答
0

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

放置 new 和显式释放器调用只会调用引用区域中的构造函数和析构函数,因此内存分配有效地被排除在对象生命周期之外

于 2011-05-17T19:52:40.170 回答