仅考虑可移动但不可复制(例如std::thread
或std::unique_ptr
)的对象,我想转移所有权这样的对象包含的资源将其作为参数传递给构造函数。我正在比较两种方法:构造函数采用对象by value与by rvalue reference。
作为std::thread
的示例,请考虑以下类Value
,其构造函数采用std::thread
按值:
#include <thread>
#include <utility>
struct Value {
Value(std::thread th): th_(std::move(th)) {}
std::thread th_;
};
所有权从参数对象转移到参数对象th
,最后转移到数据成员对象th_
。
考虑一个类似的类Reference
,在这种情况下,其构造函数通过rvalue reference来使用std::thread
:
struct Reference {
Reference(std::thread&& th): th_(std::move(th)) {}
std::thread th_;
};
在这种情况下,所有权从参数直接转移到数据成员对象th_
。
据我了解,在按值传递的情况下,参数对象和数据成员对象都是移动构造的,而对于按引用传递的情况,只有数据成员是移动构造的。总而言之,后一种方法似乎更好,因为它只需要一次移动操作,因此效率更高。
但是,有什么理由比按参考传递方法更喜欢按值传递方法吗?
按值传递是自我证明,而按引用传递则不是。对读者而言,立即显而易见的是:
(类似地,很难或不可能在实现中犯下导致上述假设无法成立的错误。]
当然,最终这些收益是否超过额外搬家建设的成本的问题是基于观点的。
(*)当然,这不适用于构造函数在内部执行的从参数到成员的移动。但是,这里的要点是,调用方可以控制their对象发生的情况:将其移到构造函数参数中,或者在该步骤发生任何故障的情况下,调用方可以进行破坏控制(可能保留该值)。
但是,有什么理由比按参考传递方法更喜欢按值传递方法吗?