可移动但不可复制的对象:按值传递与按右值引用传递?

问题描述 投票:0回答:1

仅考虑可移动不可复制的对象(例如,

std::thread
std::unique_ptr
),我想通过将其作为参数传递给构造函数。我正在比较两种方法:构造函数采用对象按值按右值引用 作为

std::thread

的示例,请考虑以下类

Value
,其构造函数采用
std::thread
by value
: #include <thread> #include <utility> struct Value { Value(std::thread th): th_(std::move(th)) {} std::thread th_; };

所有权从参数对象转移到参数对象,
th

,最后转移到数据成员对象,

th_

考虑一个类似的类,

Reference

,在本例中,其构造函数采用

std::thread
rvalue 引用
struct Reference { Reference(std::thread&& th): th_(std::move(th)) {} std::thread th_; };

在这种情况下,所有权直接从参数转移到数据成员对象,
th_


据我了解,在按值传递的情况下,参数对象和数据成员对象都是移动构造的,而对于按引用传递的情况,只有数据成员是移动构造的。总而言之,后一种方法似乎更好,因为它只需要一次移动操作,因此效率更高。

但是,是否有任何理由更喜欢按值传递方法而不是按引用传递方法?

c++ c++11 parameter-passing move-semantics ownership-semantics
1个回答
8
投票

构造函数将无条件取得仅移动类型表示的资源的所有权;
  1. 如果移动构造因任何原因抛出异常而失败,则调用者有责任处理它; (*)
  2. 如果构造函数通过抛出异常退出,资源将被释放。
  3. (同样,在实现过程中很难或不可能犯错误而导致上述假设不成立。)

当然,最终这些好处是否超过额外移动建设的成本的问题是一个基于意见的问题。

(*) 当然,这不适用于构造函数内部执行的移动,即从参数到成员的移动。然而,这里的要点是,调用者可以控制

他们的

对象发生的情况:要么将其移动到构造函数参数中,要么,如果该步骤出现任何失败,调用者可以进行损害控制(可能是为了保留价值)。

© www.soinside.com 2019 - 2024. All rights reserved.