shared_ptr魔术:)

Lidström先生的主张是,构造shared_ptr<Base> p(new Derived);不需要Base具有虚拟析构函数:


Armen Tsirunyan:“真的吗?shared_ptr会正确清理吗?在这种情况下,请您演示一下如何实现这种效果?”


DanielLidström:“ shared_ptr使用其自己的析构函数来删除具体实例。在C ++社区中,这被称为RAII。我的建议是,您将学习到有关RAII的全部知识。它将使您使用C ++的代码如此容易在任何情况下都可以使用RAII。”


Armen Tsirunyan:“我了解RAII,而且我也知道,最终pn到达0时,shared_ptr析构函数可能会删除存储的px。但是,如果px具有指向的静态类型指针Base和动态类型的指针Derived,则除非Base具有虚拟析构函数,否则会导致不确定的行为。如果我做错了,请纠正我。”


DanielLidström:“ shared_ptr知道静态类型是Concrete。自从我在其构造函数中传递它以来,它就知道这一点!看起来有点像魔术,但是我可以向您保证,它是设计使然,非常好。”


所以,判断我们。在不要求多态类具有虚拟析构函数的情况下,如何(如果可能)实现shared_ptr?提前致谢


扬帆大鱼
浏览 412回答 3
3回答

达令说

是的,可以通过这种方式实现shared_ptr。Boost确实如此,并且C ++ 11标准也需要这种行为。作为一种附加的灵活性,shared_ptr不仅可以管理引用计数器。通常将所谓的删除器放入还包含引用计数器的同一存储块中。但有趣的是,此删除器的类型不是shared_ptr类型的一部分。这称为“类型擦除”,基本上与用于实现“多态函数” boost :: function或std :: function的技术相同,用于隐藏实际的仿函数的类型。为了使您的示例正常工作,我们需要一个模板化的构造函数:template<class T>class shared_ptr{public:&nbsp; &nbsp;...&nbsp; &nbsp;template<class Y>&nbsp; &nbsp;explicit shared_ptr(Y* p);&nbsp; &nbsp;...};因此,如果您将其与Base和Derived类一起使用,则...class Base {};class Derived : public Base {};int main() {&nbsp; &nbsp;shared_ptr<Base> sp (new Derived);}...具有Y = Derived的模板化构造函数用于构造shared_ptr对象。因此,构造函数有机会创建适当的删除对象和引用计数器,并将指向该控制块的指针存储为数据成员。如果参考计数器达到零,则将使用先前创建的可感知派生的删除器来处置该对象。关于此构造函数(20.7.2.2.1),C ++ 11标准具有以下说法:要求: p必须可转换为T*。Y应为完整类型。该表达式delete p应格式正确,行为应明确,并且不得抛出异常。效果:构造一个shared_ptr对象是拥有指针p。…对于析构函数(20.7.2.2.2):效果:如果*this为空或与另一个shared_ptr实例(use_count() > 1)共享所有权,则没有副作用。否则,如果*this拥有一个对象p和一个deleteer d,d(p)则被调用。 否则,如果*this拥有一个指针p,delete p则被调用。(强调使用粗体是我的)。

喵喵时光机

创建shared_ptr时,它将在内部存储一个删除程序对象。当shared_ptr将要释放所指向的资源时,将调用此对象。由于您知道如何在构造时销毁资源,因此可以对不完整的类型使用shared_ptr。谁创建了shared_ptr,谁在其中存储了正确的删除器。例如,您可以创建一个自定义删除器:void DeleteDerived(Derived* d) { delete d; } // EDIT: no conversion needed.shared_ptr<Base> p(new Derived, DeleteDerived);p将调用DeleteDerived销毁指向的对象。该实现会自动执行此操作。

ABOUTYOU

只是,shared_ptr 使用由构造函数创建的特殊删除函数,该函数始终使用给定对象的析构函数而不是Base的析构函数,这与模板元编程有关,但确实可行。像这样template<typename SomeType>shared_ptr(SomeType *p){&nbsp; &nbsp;this->destroyer = destroyer_function<SomeType>(p);&nbsp; &nbsp;...}
打开App,查看更多内容
随时随地看视频慕课网APP