shared_ptr存储删除器如何?

时间:2014-09-03 23:28:35

标签: c++ function generics shared-ptr

我无法理解shared_ptr如何存储我给它的删除器。

最初,使用shared_ptr<int>,我认为它可能使用std::function<void(int*)>,但我可以作为删除器给出任何类型的函数(或可调用对象),只要第一个参数是int*

shared_ptr如何做到这一点?

如果这是一个愚蠢的问题,我很抱歉,我是C ++的新手,请原谅我!

编辑: 问题是:我怎么能做那样的事情?我该怎么用?任何例子?或者这是一个非常高级的话题?

2 个答案:

答案 0 :(得分:7)

删除器以及分配器是类型擦除的。共享指针管理动态分配的私有模板化控制对象,该对象通过多态基础访问,并存储所有特定于类型的状态和功能。

std::function的实现使用了类似的想法,因为它也是一种类型擦除动态管理器类,但两者通常都是完全独立实现的。

结果是,这两个课程都相对而且价格昂贵。并且只应在真正必要时使用。否则,通常更喜欢更便宜,非多态的非动态解决方案。

答案 1 :(得分:4)

  

只要第一个参数是int*,我就可以作为删除者给出任何类型的函数(或可调用对象)。

不,不是真的。 std::shared_ptr构造函数具有以下合同,可在第20.8.2.2.1节([util.smartptr.shared.const])中找到:

template<class  Y,  class  D>  shared_ptr(Y*  p,  D  d);
template<class  Y,  class  D,  class  A>  shared_ptr(Y*  p,  D  d,  A  a);
template  <class  D>  shared_ptr(nullptr_t  p,  D  d);
template  <class  D,  class  A>  shared_ptr(nullptr_t  p,  D  d,  A  a);
     

要求:p可转换为T*D应为CopyConstructible。 D的拷贝构造函数和析构函数不会抛出异常。 表达式d(p)应格式良好,应具有明确定义的行为,并且不得抛出异常。 A应为分配器(17.6.3.5)。 A的拷贝构造函数和析构函数不会抛出异常。

     

效果:构造拥有对象shared_ptr和删除者p的{​​{1}}对象。第二和第四个构造函数应使用d的副本来分配内存供内部使用。

     

后置条件:a

     

当无法获取内存以外的资源时,抛出:use_count() == 1 && get() == p或实现定义的异常。

     

异常安全:如果抛出异常,则调用bad_alloc

这个要求比删除器的第一个参数必须是正确的类型要强很多。它必须是唯一的参数(没有默认参数),因此d(p)是合法的。这比d(p)稍微灵活一些,因为返回类型可以是任何内容,但它在异常保证方面也受到更多限制。

如果你的编译器在提供带有多个必需参数的删除器时没有抓住你,那么标准库的实现就是做错了。

就如何实现它而言,利用它必须是CopyConstructible这一事实。例如,以下lambda应该可以很好地工作,并且可以赋值给std::function<void (int*)>(CopyConstructible保证确保按值捕获):

std::function<void(void)>