std::default_delete
can be specialized以允许std::unique_ptr
到painlessly manage types which have to be destroyed by calling some custom destroy-function instead of using delete p;
。
基本上有两种方法可以确保对象由C ++中的std::shared_ptr
管理:
使用std::make_shared
或std::allocate_shared
创建一个由共享指针管理的文件。这是首选方法,因为它将所需的两个存储块(有效负载和参考计数)合并为一个。尽管仅剩std::weak_ptr
个,但是对引用计数的需求仍必定会固定有效负载的内存。
然后使用a constructor或.reset()
将管理分配给共享指针。
第二种情况,当不提供自定义删除器时,很有趣:
具体来说,它定义为使用自己的未指定类型的删除器,该删除器分别使用delete [] p;
或delete p;
,具体取决于是否为数组实例化的std::shared_ptr
。
来自n4659(〜C ++ 17)的报价:
template<class Y> explicit shared_ptr(Y* p);
4要求:
Y
必须是完整类型。当delete[] p
是数组类型时的表达式T
,或者当delete p
不是数组类型时的表达式T
应当具有明确的行为,并且不抛出异常。
5个作用:如果T
不是数组类型,则构造一个拥有指针shared_ptr
的{{1}}对象。否则,构造一个拥有p
的{{1}}和一个未指定类型的删除器,该删除器调用shared_ptr
。如果p
不是数组类型,请用delete[] p
启用T
。如果引发异常,则在shared_from_this
不是数组类型时调用p
,否则将delete p
调用。
6个后置条件:T
。
[…]delete[] p
3个效果:等效于
use_count() == 1 && get() == p
。
我的问题是:
template<class Y> void reset(Y* p);
?答案 0 :(得分:4)
有没有(最好是好的)理由,而不是指定使用
std::default_delete
?
因为它不会执行您想要的操作。瞧,仅仅因为您可以专注于某件事并不意味着您可以劫持它。标准说([namespace.std]):
仅当声明依赖于用户定义的类型且该专业化满足原始模板的标准库要求且未被明确禁止时,程序才可以将任何标准库模板的模板专业化添加到命名空间std。
std::default_delete<T>::operator()(T* ptr)
的行为的标准库要求是它“在delete
上调用ptr
。”因此,您对它的专业化必须做同样的事情。
因此,在shared_ptr
执行delete ptr;
与shared_ptr
调用default_delete<T>{}(ptr)
之间应该没有区别。
这就是unique_ptr
采用删除器类型而不是依靠您对其进行专门化的原因。
从评论中:
专业化仅以正确的方式删除对象。
但这不是要求所要求的。它说:“在delete
上呼叫ptr
。”它不会说诸如“结束由ptr
指向的对象的生存期”或“销毁ptr
所引用的对象”之类的模棱两可的东西。它提供了必须发生的显式代码。
您的专业化必须坚持下去。
如果您不敢相信,论文P0722R1会这样说:
请注意,该标准要求
default_delete<T>
的专业化才能与调用delete p;
的效果相同
很明显,作者同意专门研究default_delete
并不是增加自己的行为的机制。
所以您的问题的前提是无效的。
但是,让我们假装一下您的问题是有效的,这样的专业化将起作用。是否有效,专门用于default_delete
来定制删除程序行为不是预定方法。如果是这样,则根本不需要unique_ptr
的删除对象。最多,您只需要一个参数即可告诉您指针的类型,默认为T*
。
所以这是一个很好的理由。