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);
只有成功才能移出对象。在这种情况下,接受右值引用与左值引用更好,原因至少有两个:
- 你还是可以临时通过的。
- 您需要在调用代码中明确使用
std::move
。
虽然您可以在 std::move
之后使用该指针这一事实使该变体的可读性较差。
我有一个 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);
只有成功才能移出对象。在这种情况下,接受右值引用与左值引用更好,原因至少有两个:
- 你还是可以临时通过的。
- 您需要在调用代码中明确使用
std::move
。
虽然您可以在 std::move
之后使用该指针这一事实使该变体的可读性较差。