为什么不将右值引用定义为右值表达式?

Why not define rvalue reference to be rvalue expression?

让我们考虑以下代码:

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

编译器只为可以移动的对象调用这个构造函数。那么,为什么不直接将右值引用定义为右值表达式,而不是每次都为它们编写 std::move?

ctor 成员初始化列表如下所示:

_v(v)

但这仍然是一步,而不是复制。

虽然在这种常见情况下要求 std::move 有点不幸,但人们认为在少数情况下导致 run-time 错误的隐式移动会更有害。

例如:

class Y
{
public:
    Y(const std::vector<int>& v);
};

class X {
    std::vector<int> v_;
    Y                y_;
public:
    X(std::vector<int>&& v): v_(v), y_(v) {}
};

在此修改后的示例中,X 的构造函数使用了两次 v。如果第一次使用 v 隐式移动,那么第二次使用 v 很可能得不到预期的值。

因此避免意外"use after move",如果它有名字,那么它可以多次使用,因此将其视为左值更安全。