我有一个类,该类基本上是一个队列,用于在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
/* ... */
}
答案 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);
并仅成功移动对象。至少由于以下两个原因,在这种情况下,接受右值引用与左值引用比较好:
std::move
。尽管您可以在std::move
之后使用该指针,但使该变体的可读性较差。