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

std::unique_ptr test before taking ownership

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

实际调用入队方法是这样的:

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

和签名:

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

问题是 put() 方法必须检查一些条件来决定是否可以将对象添加到队列中。如果条件为假,该方法简单地 returns 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);

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

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

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

  1. 你还是可以临时通过的。
  2. 您需要在调用代码中明确使用 std::move

虽然您可以在 std::move 之后使用该指针这一事实使该变体的可读性较差。