为什么shared_ptr删除程序必须是CopyConstructible的? [英] Why do shared_ptr deleters have to be CopyConstructible?

查看:90
本文介绍了为什么shared_ptr删除程序必须是CopyConstructible的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++ 11中,std::shared_ptr具有四个构造函数,可以将其传递给类型为D的删除对象d.这些构造函数的签名如下:

In C++11 std::shared_ptr has four constructors which can be passed deleter objects d of type D. The signatures of these constructors are the following:

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);

该标准要求 [util.smartptr.shared.const] 类型D是可复制构造的.为什么需要这个?如果shared_ptr复制了d,那么这些删除器中的哪个会被调用? shared_ptr不可能只保留一个删除器吗?如果可以复制dshared_ptr拥有删除器是什么意思?

The standard requires in [util.smartptr.shared.const] type D to be CopyConstructible. Why is this needed? If shared_ptr makes copies of d then which of these deleters might get called? Wouldn't it possible for a shared_ptr only to keep a single deleter around? What does it mean for a shared_ptr to own a deleter if d can be copied?

CopyConstructible要求背后的原理是什么?

PS:此要求可能会使shared_ptr的编写删除程序变得复杂. unique_ptr似乎对其删除器有更好的要求.

PS: This requirement might complicate writing deleters for shared_ptr. unique_ptr seems to have much better requirements for its deleter.

推荐答案

这个问题非常令人困惑,以至于我通过电子邮件发送给Peter Dimov(boost::shared_ptr的实现者,并参与了std::shared_ptr的标准化工作)

This question was perplexing enough that I emailed Peter Dimov (implementer of boost::shared_ptr and involved in standardization of std::shared_ptr)

以下是他所说的内容(经他的许可转载):

Here's the gist of what he said (reprinted with his permission):

我的猜测是,Deleter实际上必须是CopyConstructible的,因为 C ++ 03的遗物,其中不存在移动语义.

My guess is that the Deleter had to be CopyConstructible really only as a relic of C++03 where move semantics didn’t exist.

您的猜测是正确的.当指定shared_ptr时,右值引用 还不存在.如今,我们应该能够满足要求 无需移动即可构建.

Your guess is correct. When shared_ptr was specified rvalue references didn't exist yet. Nowadays we should be able to get by with requiring nothrow move-constructible.

在什么时候有一个微妙之处

There is one subtlety in that when

pi_ = new sp_counted_impl_pd<P, D>(p, d);

抛出,必须完全保留d才能使清理d(p)正常工作,但是我 认为这将不是问题(尽管我实际上并没有 试图使实现易于移动).
[...]
我认为对于 实现对其进行定义,以便在抛出new时将保留d 保持其原始状态.

throws, d must be left intact for the cleanup d(p) to work, but I think that this would not be a problem (although I haven't actually tried to make the implementation move-friendly).
[...]
I think that there will be no problem for the implementation to define it so that when the new throws, d will be left in its original state.

如果我们走得更远并且允许D具有投掷移动构造函数,事情将会变得 更复杂.但是我们不会. :-)

If we go further and allow D to have a throwing move constructor, things get more complicated. But we won't. :-)

这篇关于为什么shared_ptr删除程序必须是CopyConstructible的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆