【发布时间】:2011-04-23 10:08:57
【问题描述】:
Mr. Lidström and I had an argument :)
先生。 Lidström 声称构造 shared_ptr<Base> p(new Derived); 不需要 Base 具有虚拟析构函数:
Armen Tsirunyan:“真的吗?shared_ptr 会正确清理吗?您能否在这种情况下演示如何实现该效果?”
Daniel Lidström:“shared_ptr 使用自己的析构函数来删除 Concrete 实例。这在 C++ 社区中被称为 RAII。我的建议是你学习所有您可以了解 RAII。当您在所有情况下使用 RAII 时,它将使您的 C++ 编码变得更加容易。"
Armen Tsirunyan:“我知道 RAII,我也知道最终 shared_ptr 析构函数可能会在 pn 达到 0 时删除存储的 px。但是如果 px 有静态指向
Base的类型指针和指向Derived的动态类型指针,那么除非Base具有虚拟析构函数,否则这将导致未定义的行为。如果我错了,请纠正我。”Daniel Lidström:“shared_ptr 知道静态类型是具体的。它知道这一点,因为我在它的构造函数中传递了它!看起来有点像魔术,但我可以向您保证,这是设计使然,非常好。”
所以,判断我们。如何在不要求多态类具有虚拟析构函数的情况下实现 shared_ptr (如果是的话)? 提前致谢
【问题讨论】:
-
你可以链接到original thread。
-
另一个有趣的事情是
shared_ptr<void> p(new Derived)也会通过它的析构函数来销毁Derived对象,不管它是否是virtual。 -
提问的好方法:)
-
尽管 shared_ptr 允许这样做,但是将一个类设计为没有虚拟 dtor 的基础是一个非常糟糕的主意。 Daniel 关于 RAII 的 cmets 具有误导性——它与此无关——但引用的对话听起来像是一个简单的误解(以及对 shared_ptr 如何工作的错误假设)。
-
不是 RAII,而是类型擦除析构函数。您必须小心,因为
shared_ptr<T>( (T*)new U() )其中struct U:T不会做正确的事情(这可以很容易地间接完成,例如采用T*并传递U*的函数)跨度>
标签: c++ destructor smart-pointers