取得所有权之前先进行std :: unique_ptr测试

时间:2018-08-13 15:54:35

标签: c++ move-semantics unique-ptr

我有一个类,该类基本上是一个队列,用于在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
    /* ... */
}

2 个答案:

答案 0 :(得分:5)

是的,很好。替代方法是:

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.
}

您的方式的优点是,如果...中的代码抛出,则调用方保留所有权。

答案 1 :(得分:2)

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

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

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

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

并仅成功移动对象。至少由于以下两个原因,在这种情况下,接受右值引用与左值引用比较好:

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

尽管您可以在std::move之后使用该指针,但使该变体的可读性较差。