【问题标题】:Move a unique_ptr with custom deleter to a shared_ptr将带有自定义删除器的 unique_ptr 移动到 shared_ptr
【发布时间】:2015-09-11 02:55:59
【问题描述】:

我有一个函数可以创建一个带有自定义删除器的 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);
}

在该函数的客户端代码中,我想将 unique_ptr 移动到 shared_ptr,但由于我不知道自定义删除器的 decltype,我不知道该怎么做在函数之外。

我猜它应该是这样的:

auto uniquePtr = give_unique_ptr();
auto sharedPtr = std::shared_ptr<..??..>(std::move(uniquePtr));

我必须写什么而不是 ..??.. 才能获得正确的类型?

如果可能,shared_ptr 是否会表现良好并在使用次数达到零时调用我在 give_unique_ptr() 函数中创建的自定义删除器?

【问题讨论】:

  • 记住shared_ptr 删除删除器。唯一的模板参数是当前视图中指向的类型。
  • @o11c 这是什么意思?我尝试了@Nawaz 提出的解决方案,删除器在shared_ptr 被销毁后被调用。
  • 表示删除者的类型与shared_ptr的类型无关。您甚至可以转换为 shared_ptr&lt;char&gt;,它仍然会调用原始删除器。

标签: c++ c++11 shared-ptr c++14 unique-ptr


【解决方案1】:

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

std::shared_ptr<int> sharedPtr(std::move(uniquePtr));

std::shared_ptr 的构造函数将负责删除器。


但是,如果您希望推断出 类型,那么:

auto sharedPtr = make_shared_from(std::move(uniquePtr));

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

希望对您有所帮助。

【讨论】:

  • IMO,最好让make_shared_from 采用右值引用,使其向外可见
  • @RyanHaining 甚至是一个值,在大多数情况下这更符合 C++11 的习惯。
  • @o11c 我不能说我同意,除了招致额外的举动之外还有什么不同吗?
  • @o11c shared_ptr 构造函数采用unique_ptr&amp;&amp;,因此很难将其称为“惯用”来获取值。自定义删除器可能会更大,以至于额外的移动可能不像您想象的那么微不足道。通过。移动指针很简单,移动unique_ptr 则不然。
  • &amp;&amp; 对于 sink 参数是有意义的并且是惯用的,即使你有一个 sink-only 类型。无论如何,使用内联函数,所有这些寄存器/指针计数都无关紧要。 @Ryan 关于“我们不知道自定义删除器的成本”的观点是一个很好的观点。我会选择 std::shared_ptr&lt;T&gt; share_unique_ptr( std::unique_ptr&lt;T,D&gt;&amp;&amp; ptr ) 我自己作为名称/签名:返回共享 ptr 的事实应该是函数名称的一部分。
【解决方案2】:
auto uniquePtr = give_unique_ptr();
auto sharedPtr = std::shared_ptr<decltype(uniquePtr)::element_type>(std::move(uniquePtr));

是的,shared_ptr 将存储 - 并在以后使用 - 自定义删除器。

【讨论】:

    猜你喜欢
    • 2018-08-26
    • 1970-01-01
    • 2015-02-04
    • 1970-01-01
    • 2018-10-16
    • 2020-06-19
    • 2015-08-15
    • 2019-01-16
    • 2016-11-23
    相关资源
    最近更新 更多