首页 > 解决方案 > 可能失败的 unique_ptr 移动的函数签名?

问题描述

假设我正在编写一个enqueue()接受 a 的函数unique_ptr,但我只想在 enqueue 返回成功时声明它的所有权。如果队列已满,我想unique_ptr保持原样(用户可以稍后重试相同的项目)

bool enqueue(std::unique_ptr&& item){
  if(!vector.full()){
    vector.emplace(std::move(item));
    return true;
  }
  return false;
}
// usage
auto item_ptr = make_unique<>();
while(!enqueue(std::move(item_ptr))){
// item_ptr is not moved
}

我也可以定义函数来取一个左值引用

bool enqueue(std::unique_ptr& item)
while(!enqueue(item_ptr)){
// item_ptr is not moved
}

我不确定该选择哪一个,它们似乎都有点反模式,因为通常std::move表示删除了 unique_ptr(大多数时候,我使用unique_ptr按值取值的函数),也许有更好的解决方案?

标签: c++unique-ptrmove-semantics

解决方案


带有 RValue 引用的第一个版本接受一个临时的。因此,如果移动没有发生,您将在一个临时实例中有一个实例,该实例std::unique_ptr将很快被删除。这就是让我不确定它是否是一个好的选择(或邀请令人惊讶的效果)的原因。

至少,人们应该意识到这一点。

关于问题

如果你这样做会发生什么 while (!enqueue(make_unique<>()))...

我做了一个 MCVE(只是为了确定):

#include <memory>
#include <iostream>

struct Test {
  Test() { std::cout << "Test::Test()\n"; }
  ~Test() { std::cout << "Test::~Test()\n"; }
};

bool enqueue(std::unique_ptr<Test>&& item)
{
  return false;
}

int main()
{
  for (int i = 0; i < 3 && !enqueue(std::make_unique<Test>()); ++i);
}

输出:

Test::Test()
Test::~Test()
Test::Test()
Test::~Test()
Test::Test()
Test::~Test()

关于大肠杆菌的演示

如果它旨在防止“滥用”并确保enqueue()不会临时调用 RValue 版本,则可以删除。


推荐阅读