【发布时间】:2018-08-13 15:54:34
【问题描述】:
我有一个类,它基本上是一个队列,用于在 2 个线程之间传输动态分配的对象。第一个线程创建对象,第二个线程消耗它们。我使用 std::unique_ptr 将对象所有权从线程 1 传递到线程 2。
实际上调用将对象放入队列的方法是这样的:
queue.put(std::move(unique_ptr_to_my_object));
和签名:
bool Queue::put(std::unique_ptr<T> p);
问题是put() 方法必须检查一些条件来决定是否可以将对象添加到队列中。如果条件为假,则该方法仅返回假以指示它无法将对象添加到队列中,但该对象被销毁,因为所有权已被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
/* ... */
}
【问题讨论】:
-
我会将修改后的函数改为
Queue::put(std::unique_ptr<T>&& ref)。 -
@Tyker 不,它没有。它需要一个右值的引用。直到您使用它来分配或初始化它实际移动的东西。请记住,只有移动构造函数或移动赋值运算符才能真正移动某些东西。
-
@NathanOliver 还是为什么?在这种情况下,您可能确实希望限制为左值引用......否则如果放置失败,则只有暂时的剩余抱着婴儿。
-
@MartinBonner 为什么将函数限制为仅左值?如果我从某个函数中得到
unique_ptr并且并不关心它是否已移入队列,为什么我需要先使其成为左值。 -
@James 我认为您的原始解决方案实际上是最好的解决方案。在失败的情况下返回对象是违反直觉的,并且使用反转逻辑(它有效地返回 false 表示成功,返回 true 表示失败)。我要做的唯一更改是重命名方法
tryPut,以便一目了然它可能会失败。
标签: c++ move-semantics unique-ptr