我无法理解shared_ptr
如何存储我给它的删除器。
最初,使用shared_ptr<int>
,我认为它可能使用std::function<void(int*)>
,但我可以作为删除器给出任何类型的函数(或可调用对象),只要第一个参数是int*
。
shared_ptr
如何做到这一点?
如果这是一个愚蠢的问题,我很抱歉,我是C ++的新手,请原谅我!
编辑: 问题是:我怎么能做那样的事情?我该怎么用?任何例子?或者这是一个非常高级的话题?
答案 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)>