2014-09-03 75 views
7

我无法理解shared_ptr如何存储我给它的删除程序。shared_ptr商店删除器如何?

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

shared_ptr如何做到这一点?

对不起,如果这是一个愚蠢的问题,我是C++的新手,原谅我!

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

+1

你想了解你的特殊的编译器和库? (如果是这样,告诉我们你正在使用哪一个)或者C++标准对所有符合实现的说法? – 2014-09-03 23:31:15

+0

我会知道我该怎么做这样的事情。我将编辑消息。 – Toccio 2014-09-03 23:32:45

+1

@Toccio:该行为由模板启用。这是一个高级话题。这个问题的荣誉,这是合理的,并且很好。 – Jon 2014-09-03 23:36:06

回答

7

删除程序和分配程序都进行了类型擦除。共享指针管理一个动态分配的私有模板控制对象,通过一个多态基地访问该控制对象,并存储所有特定于类型的状态和功能。

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

结果是两个班都相对“昂贵”,只有在真正需要时才能使用。否则,更便宜的,非多态的非动态解决方案通常是优选的。

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的拷贝构造函数和析构函数不得抛出异常。

影响:构造一个拥有对象p和删除者d的对象。第二和第四个构造函数应使用a的副本分配内存供内部使用。

后续条件:use_count() == 1 && get() == p

抛出:bad_alloc,或当无法获取内存以外的其他资源时执行定义的异常。

异常安全:如果引发异常,则调用d(p)

这个要求比删除者的第一个参数必须是正确的类型强得多。它必须是唯一的参数(没有默认参数),因此d(p)是合法的。这比std::function<void (int*)>稍微灵活一点,因为返回类型可以是任何东西,但是对于异常保证它也更加受限制。

如果在为多个必需参数提供删除程序时,编译器无法捕捉到您,则标准库实现正在做一些相当错误的事情。

至于如何实现它,利用它必须是CopyConstructible的事实。例如,下面的拉姆达应该工作得很好,并分配给std::function<void(void)>(的拷贝构造保障可确保价值的作品,捕捉):

[d, p] { d(p); } 
+0

@hvd:我说“必须是没有默认参数的唯一参数”。在你的例子中,它是。 – 2014-09-03 23:42:13

+0

啊,谢谢你清理那个,我误解了你的答案。 – hvd 2014-09-03 23:43:48

+1

“如果你的编译器在你提供了一个需要多个参数的删除器时没有抓住你,它就会做一些相当错误的事情。”不必要。违反*要求*条款导致UB。编译器不需要诊断它。 – 2014-09-03 23:51:43

相关问题