【问题标题】:Movable but non-copyable objects: passing by value vs by reference?可移动但不可复制的对象:按值传递还是按引用传递?
【发布时间】:2020-03-17 23:39:01
【问题描述】:

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


    【解决方案1】:

    按值传递是自我记录,而按引用传递则不是。读者立即明白:

    1. 构造函数将无条件地取得由只移动类型表示的资源的所有权;
    2. 如果移动构造由于某种原因引发异常而失败,则调用者有责任处理它; (*)
    3. 如果构造函数通过抛出异常退出,资源将被处理掉。

    (同样地,在实现中很难或不可能出现导致上述假设不成立的错误。)

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

    (*) 当然,这不适用于构造函数内部执行的移动,从参数到成员。然而,这里的重点是调用者可以控制 他们的 对象发生的事情:要么将其移动到构造函数参数中,要么在该步骤发生任何故障时,调用者可以执行损害控制(可能保留价值)。

    【讨论】:

      猜你喜欢
      • 2013-01-21
      • 2013-02-09
      • 2013-05-03
      • 2020-05-28
      • 2015-06-12
      • 2015-01-12
      • 2016-03-10
      • 2012-07-21
      • 2011-04-20
      相关资源
      最近更新 更多