std::unique_ptr 在获得所有权之前进行测试

std::unique_ptr test before taking ownership

本文关键字:测试 所有权 unique ptr std      更新时间:2023-10-16

我有一个类,它基本上是一个队列,用于在 2 个线程之间传输动态分配的对象。第一个线程创建对象,第二个线程使用它们。我使用std::unique_ptr将对象所有权从线程 1 传递到线程 2。

实际上,对将对象放入队列的方法的调用如下所示:

queue.put(std::move(unique_ptr_to_my_object));

和签名:

bool Queue::put(std::unique_ptr<T> p);

问题是put()方法必须检查某些条件才能决定是否可以将对象添加到队列中。如果条件为 false,该方法只需返回 false 以指示它无法将对象添加到队列中,但对象被销毁,因为所有权已被put()取得。

所以我想知道是否可以像这样重写put()或者是否有更好的解决方案:

bool Queue::put(std::unique_ptr<T> &ref) {
if(CANNOT_ADD)
return false; // ownership remains in the calling function
std::unique_ptr<T> p = std::move(ref); // we know we can add so take ownership
/* ... */
}

是的,这很好。 另一种选择是:

std::unique_ptr<T> Queue::put(std::unique_ptr<T> p) {
if (CANNOT_ADD)
return p; // Ownership returned to caller.
/* ... */
return {}; // Return empty nullptr to indicate success.
}

您的方式具有以下优势:如果...中的代码抛出,调用方将保留所有权。

您可以将函数的签名更改为:

std::unique_ptr<T> Queue::put(std::unique_ptr<T> p);

因此,如果该函数无法接受该对象,它将返回该指针,否则nullptr。另一种解决方案是有条件地取得所有权:

bool Queue::put(std::unique_ptr<T> &&p);

并且只有在成功时才移出对象。在这种情况下,接受右值引用与左值 1 更好,原因至少有 2 个:

  1. 您仍然可以暂时通过。
  2. 需要在调用代码时显式使用std::move

尽管您可以在std::move制作此变体后使用该指针这一事实的可读性较差。