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

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

仅考虑可移动不可复制(例如std::threadstd::unique_ptr)的对象,我想转移所有权这样的对象包含的资源将其作为参数传递给构造函数。我正在比较两种方法:构造函数采用对象by valueby 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_

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

但是,有什么理由比按参考传递方法更喜欢按值传递方法吗?

c++ c++11 parameter-passing move-semantics ownership-semantics
2个回答
4
投票

按值传递是自我证明,而按引用传递则不是。对读者而言,立即显而易见的是:

  1. 构造函数将无条件获取仅移动类型表示的资源的所有权;
  2. 如果移动构造由于任何原因而引发异常而失败,则呼叫者有责任对其进行处理; (*)
  3. 如果构造函数抛出异常退出,资源将被处置。

(类似地,很难或不可能在实现中犯下导致上述假设无法成立的错误。]

当然,最终这些收益是否超过额外搬家建设的成本的问题是基于观点的。

(*)当然,这不适用于构造函数在内部执行的从参数到成员的移动。但是,这里的要点是,调用方可以控制their对象发生的情况:将其移到构造函数参数中,或者在该步骤发生任何故障的情况下,调用方可以进行破坏控制(可能保留该值)。


2
投票
但是,有什么理由比按参考传递方法更喜欢按值传递方法吗?
© www.soinside.com 2019 - 2024. All rights reserved.