代码之家  ›  专栏  ›  技术社区  ›  Deduplicator

默认情况下“std::shared_ptr”不应该使用“std::default_delete”吗?

  •  3
  • Deduplicator  · 技术社区  · 6 年前

    std::default_delete can be specialized 允许 std::unique_ptr S至 painlessly manage types which have to be destroyed by calling some custom destroy-function instead of using delete p; 是的。

    基本上有两种方法可以确保对象由 std::shared_ptr 在C++中:

    1. 创建由共享指针管理的 std::make_shared std::allocate_shared 是的。这是首选方法,因为它将所需的两个内存块(负载和引用计数)合并为一个。尽管只有 std::weak_ptr 在剩下的时间里,对引用计数的需求也会必然地为有效负载固定内存。

    2. 之后,使用 a constructor .reset() 是的。

    第二种情况是,当不提供自定义删除程序时:

    具体来说,它被定义为使用自己的未指定类型的deleter delete [] p; 删除p; 分别取决于 STD:SyrdypTR 是否为数组实例化。

    来自N465 9(~c++ 17)的引用:

    template<class Y> explicit shared_ptr(Y* p);
    

    4要求: Y 应为完整类型。表达 delete[] p ,当 T 是数组类型,或 delete p ,当 T 不是数组类型,应具有良好的行为,并且不应引发异常。
    5周:何时 T型 不是数组类型,构造 shared_ptr 拥有指针的对象 p 是的。否则,将构造 共享的 拥有 第页 一个不特定类型的删除者 删除[]p 是的。什么时候? T型 不是数组类型,启用 shared_from_this 具有 第页 是的。如果抛出异常, 删除p 被调用的时间 T型 不是数组类型, 删除[]p 否则。
    6后置条件: use_count() == 1 && get() == p 是的。
    []

    template<class Y> void reset(Y* p);
    

    3 eects:相当于 shared_ptr(p).swap(*this) 是的。

    我的问题是:

    1. 是否有一个,最好是好的,不指定使用的原因 std::默认删除 相反?
    2. 是否有任何有效的(和潜在的有用的?)密码被那个改变打破了?
    3. 已经有人提议这么做了吗?
    1 回复  |  直到 6 年前
        1
  •  4
  •   Nicol Bolas    6 年前

    是否有一个,最好是好的,不指定使用的原因 std::default_delete 相反?

    因为它做不到你想要的。你看,仅仅因为你能专门化一些东西并不意味着你能劫持它。标准上说([namespace.std]):

    只有当声明依赖于用户定义的类型并且专门化满足原始模板的标准库要求且未被明确禁止时,程序才能将任何标准库模板的模板专门化添加到命名空间std。

    标准库要求 std::default_delete<T>::operator()(T* ptr) 他的行为是 delete ptr “所以你的专业化 必须 做同样的事。

    因此,拥有 shared_ptr 执行 delete ptr; 并且拥有 共享的 援引 default_delete<T>{}(ptr) 是的。

    这就是为什么 unique_ptr 采用deleter类型,而不是依赖于您对其进行专门化。


    从评论中:

    专门化以唯一正确的方式删除对象。

    但要求并不是这么说的。上面写着“电话 删除 PTR公司 “它没有说一些更含糊不清的东西,比如”结束了 PTR公司 “或”销毁引用的对象 PTR公司 “。它给出了必须发生的显式代码。

    你的专业必须坚持到底。

    如果你仍然不相信,报纸 P0722R1 这么说:

    请注意,标准要求专门化 default_delete<T> 和打电话一样的效果 delete p; 我是说,

    很明显,作者同意 default_delete 不是添加自己行为的机制。

    所以你问题的前提是无效的。


    不过,让我们假设一下,你的问题是有效的,这样的专业化是可行的。是否有效,专业化 默认删除 自定义删除器行为不是 打算 这样做的方法。如果是故意的,就不需要deleter对象 独特的 完全。最多,您只需要一个参数来告诉您指针类型是什么,它默认为 T* 是的。

    所以这是一个不这么做的好理由。