【问题标题】:Why to move rvalue reference in a move constructor?为什么要在移动构造函数中移动右值引用?
【发布时间】:2019-05-23 20:20:03
【问题描述】:

我遇到了以下代码:

class X {
    std::vector<int> m_v;
public:
    X(std::vector<int>&& v) : m_v(std::move(v)) {

};

参数 v 已经是一个右值引用 - 那么为什么我们需要对它应用 std::move 呢?

【问题讨论】:

  • v 被命名为对象。每个命名对象都是左值。您需要使用move将Lvalue转换为Rvalue引用,然后才能调用vector的move构造函数。
  • 谢谢,但那是一个动作演员。它只为右值调用,不能为左值调用。左值是怎么产生的??
  • 考虑这个代码vector&lt;int&gt; v; X x{move(v)}; 所以move(v) 是右值 - 临时的?不,它将 Lvalue 转换为 Rvalue 引用(严格来说它是 Xvalue)。现在在 X 的 ctor 中,您可以决定是要复制 v 还是移动它:m_v(v) 进行复制,但这个 m_v(move(v)) 移动。
  • 好吧...让我们考虑 m_v(v)。 v 的类型是 std::vector&& 即右值引用。所以 m_v(v) 使用 move-ctor,而不是 copy-ctor。这很明显,不是吗?
  • 所以试试这段代码,看看移动矢量的内容,它会保持不变。因为会复制。测试一下。

标签: c++11 move-semantics


【解决方案1】:

简而言之:每个命名对象都是左值,即使v 是对右值的引用,您也需要使用move 来强制调用移动ctor。

From reference - value categories

即使变量的类型是右值引用,表达式 由它的名字组成的是一个lvalue表达式;

现在您的数据成员 m_v 是包含复制和移动构造函数的向量。 接下来的句子描述了哪个被调用,reference

如果同时提供了复制和移动构造函数并且没有其他构造函数 构造函数是可行的,重载决议选择移动 如果参数是相同类型的右值(一个 xvalue 例如 std::move 或纯右值(例如无名)的结果 临时(C++17 前)),并选择复制构造函数,如果 参数是左值(命名对象或函数/运算符返回 左值引用)。

所以当你写的时候:

m_v(std::move(v)) // move ctor is called because you are passing Xvalue

但是在这个:

m_v(v) // copy ctor is called because v as named object is passed

【讨论】:

    猜你喜欢
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 2014-04-02
    • 1970-01-01
    • 2019-01-22
    • 1970-01-01
    • 1970-01-01
    • 2020-04-26
    相关资源
    最近更新 更多