首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >shared_ptr魔术:)

shared_ptr魔术:)
EN

Stack Overflow用户
提问于 2010-10-10 09:41:01
回答 3查看 16.6K关注 0票数 95

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使用自己的析构函数删除具体实例。这在C++社区中被称为RAII。我的建议是,您应该尽可能地了解RAII。在所有情况下使用RAII都会使您的C++编码更加容易。”

Armen Tsirunyan:“我知道RAII,我也知道当pn达到0时,shared_ptr析构函数可能会删除存储的px。但是如果px有指向Base的静态类型指针和指向Derived的动态类型指针,那么除非Base有一个虚拟析构函数,否则这将导致未定义的行为。如果我错了,请纠正我。”

Daniel Lidstr m:“shared_ptr知道静态类型是具体的。它知道这一点,因为我在它的构造函数中传递了它!看起来有点神奇,但我可以向你保证,它是设计的,而且非常漂亮。”

所以,评判我们。如何才能(如果是)实现shared_ptr而不需要多态类具有虚拟析构函数?提前感谢

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-10-10 11:18:06

是的,用这种方式实现shared_ptr是可能的。Boost does和C++11标准也要求这种行为。作为一种额外的灵活性,shared_ptr管理的不仅仅是一个引用计数器。所谓的删除器通常被放入同样包含引用计数器的内存块中。但有趣的是,这个删除器的类型不是shared_ptr类型的一部分。这被称为“类型擦除”,并且基本上是用于实现“多态函数”boost::functionstd::function以隐藏实际函子类型的技术。要使示例工作,我们需要一个模板化的构造函数:

代码语言:javascript
复制
template<class T>
class shared_ptr
{
public:
   ...
   template<class Y>
   explicit shared_ptr(Y* p);
   ...
};

所以,如果你在你的类BaseDerived中使用这个..。

代码语言:javascript
复制
class Base {};
class Derived : public Base {};

int main() {
   shared_ptr<Base> sp (new Derived);
}

..。带有Y=Derived的模板构造函数用于构造shared_ptr对象。因此,构造函数有机会创建适当的删除对象和引用计数器,并将指向此控件块的指针存储为数据成员。如果引用计数器达到零,则将使用先前创建的和Derived-aware删除器来释放对象。

C++11标准对此构造函数有如下说明(20.7.2.2.1):

要求:p必须可转换为T*Y应该是一个完整的类型。delete p 一词应格式良好,行为应明确,不得抛出异常。

效果:构造一个shared_ptr对象,拥有指针

以及破坏者(20.7.2.2.2):

效果:如果*this为空或与另一个shared_ptr实例(use_count() > 1)共享所有权,则没有副作用。否则,如果*this拥有对象p和删除器d,则调用d(p)。否则,如果*this 拥有指针p**,和** delete p ,则为.。

(用粗体强调是我的)。

票数 77
EN

Stack Overflow用户

发布于 2010-10-10 09:47:53

当创建shared_ptr时,它会在其内部存储一个删除对象。当shared_ptr即将释放指定资源时,将调用此对象。由于您知道如何在构建时销毁资源,所以可以使用不完整类型的shared_ptr。创建shared_ptr的人在那里存储了一个正确的删除器。

例如,您可以创建一个自定义删除器:

代码语言:javascript
复制
void DeleteDerived(Derived* d) { delete d; } // EDIT: no conversion needed.

shared_ptr<Base> p(new Derived, DeleteDerived);

P将调用DeleteDerived来销毁指向的对象。该实现自动执行此操作。

票数 30
EN

Stack Overflow用户

发布于 2010-10-10 09:46:02

简单地说,

shared_ptr使用由构造函数创建的特殊删除函数,构造函数总是使用给定对象的析构函数,而不是Base的析构函数,这是模板元编程中的一些工作,但它有效。

类似这样的东西

代码语言:javascript
复制
template<typename SomeType>
shared_ptr(SomeType *p)
{
   this->destroyer = destroyer_function<SomeType>(p);
   ...
}
票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3899790

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档