直接调用(虚拟)析构函数是否有效?
在这个答案中,Ryan直接调用虚拟析构函数。我已经在VS2010中测试了代码,它正确地调用了所有析构函数(使用日志语句进行测试)。这样做实际上有效吗?这种方法有哪些问题、缺陷甚至优点是什么?
我只能将其视为真正强制重置实际类型的一种方法,即使它们没有覆盖虚拟重置函数,因为它们至少必须在析构函数中进行清理。
另外,调用析构函数到底会带来什么样的副作用?在这样的析构函数调用之后使用该对象是否是未定义的行为?如果立即使用 new (this) MyClass();
调用重新初始化它会怎样?
In this answer, Ryan directly calls the virtual destructor. I've tested the code in VS2010, and it correctly calls all destructors (tested with logging statements). Is it actually valid to do so? What are the problems, flaws or even the good points of such an approach?
I can only think of it as a way to really force a reset of the actual type, even if they don't override a virtual reset
function, since they atleast have to clean up in their destructors.
Also, eactly what kind of side-effects does a call to the destructor bring? 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
手动调用析构函数是完全有效的事情,无论它是否是虚拟的。您只想确保每次调用构造函数时只调用一次。
是的。
仍然可怕地未定义。
不要手动破坏一个对象,除非你必须手动放置它,例如使用新的放置或类似的东西,并且绝对不要像这样重新初始化一个被破坏的对象并希望避免UB。像 std::vector 这样的类非常明确地访问被破坏的对象 UB,并且即使您随后在其位置创建了一个新元素,它仍然是 UB。
Calling a destructor manually is a perfectly valid thing, regardless of if it's virtual. You just want to make sure that it's just called once for every constructor call.
Yes.
Still horrifically undefined.
Do not manually destruct an object unless you had to manually place it, e.g. with placement new or some equivalent, and definitely do not ever re-initialize a destructed object like that and hope to avoid UB. Classes like
std::vector
very explicitly make accessing destroyed objects UB, and it remains UB even if you then make a new element in it's place.涉及一个且仅一个构造的有效使用示例:
这在例如实现变体类型时非常有用(警告:异常安全留给读者作为练习)。 C++0x 无限制联合对于类类型具有类似的用途。
请注意,对于类类型,如果您没有调用析构函数,则上述内容将是 UB。
An example of valid use involving one and only one construction:
This can be useful when e.g. implementing a variant type (warning: exception-safety left as an exercise to the reader). C++0x unrestricted unions will have similar uses for class types.
Note that for a class type, the above would be UB if you did not call the destructor.
只要您在预分配的 POD 内存块之上调用 placement new,就可以完全有效地调用任何析构函数(无论是否是虚拟析构函数)来解除分配。
放置 new 和显式释放器调用只会调用引用区域中的构造函数和析构函数,因此内存分配实际上被排除在对象生命周期之外
As long as you are calling placement new on top of your pre-allocated chunk of POD memory, its perfectly valid to deallocate invoking any destructor, virtual or not.
placement new and explicit deallocator invocation will just invoke the constructor and destructor in the referenced areas, so memory allocation is effectively factored out of the object lifecycle