将带有自定义删除器的unique_ptr移动到shared_ptr

j00*_*0hi 23 c++ shared-ptr unique-ptr c++11 c++14

我有一个函数,它使用自定义删除器创建unique_ptr并返回它:

auto give_unique_ptr() {
    auto deleter = [](int* pi) {
        delete pi;
    };
    int* i = new int{1234};
    return std::unique_ptr<int, decltype(deleter)>(i, deleter);
}
Run Code Online (Sandbox Code Playgroud)

在该函数的客户端代码中,我想移动unique_ptr到a shared_ptr,但我不知道如何做到这一点,因为我不知道我的自定义删除器的decltype在函数之外.

我想它应该看起来像这样:

auto uniquePtr = give_unique_ptr();
auto sharedPtr = std::shared_ptr<..??..>(std::move(uniquePtr));
Run Code Online (Sandbox Code Playgroud)

我需要写什么而不是.. ?? ..来获得正确的类型?

如果这是可能的,那么当它的使用计数达到零时,它会shared_ptr表现得很好并调用我在give_unique_ptr()函数内创建的自定义删除器吗?

Naw*_*waz 19

如果您知道(或想要显式键入)对象的类型,那么您可以这样做:

std::shared_ptr<int> sharedPtr(std::move(uniquePtr));
Run Code Online (Sandbox Code Playgroud)

将建造者std::shared_ptr照顾deletor.


但是,如果您想要推断类型,那么:

auto sharedPtr = make_shared_from(std::move(uniquePtr));
Run Code Online (Sandbox Code Playgroud)

在哪里make_shared_from:

template<typename T, typename D>
std::shared_ptr<T> make_shared_from(std::unique_ptr<T,D> && p)
{
   //D is deduced but it is of no use here!
   //We need only `T` here, the rest will be taken 
   //care by the constructor of shared_ptr
   return std::shared_ptr<T>(std::move(p));
};
Run Code Online (Sandbox Code Playgroud)

希望有所帮助.

  • @RyanHaining甚至是一个值,在大多数情况下更多的是C++ 11惯用语. (3认同)
  • 即使你只有一个接收器类型,`&&`for sink参数也是有意义的并且是惯用的.使用内联函数,无论如何,所有这些寄存器/指针计数都无关紧要.而@ Ryan关于"我们不知道自定义删除费用多少"的观点是一个很好的观点.我选择`std :: shared_ptr <T> share_unique_ptr(std :: unique_ptr <T,D> && ptr)`我自己作为名称/签名:这个返回共享ptr的事实应该是函数名称的一部分. (3认同)
  • 国际海事组织,让'make_shared_from`采用右值参考使其向外可见以使其从 (2认同)
  • @ o11c的`shared_ptr`构造函数采用`unique_ptr &&`,因此很难将其称为"惯用"来获取值.自定义删除器可能会更大,以至于额外的移动可能不像您想象的那样可以忽略不计.通过.移动指针是微不足道的,移动'unique_ptr`不是. (2认同)

T.C*_*.C. 15

auto uniquePtr = give_unique_ptr();
auto sharedPtr = std::shared_ptr<decltype(uniquePtr)::element_type>(std::move(uniquePtr));
Run Code Online (Sandbox Code Playgroud)

是的,shared_ptr将存储 - 以及以后使用 - 自定义删除器.