为什么不将右值引用定义为右值表达式?
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",如果它有名字,那么它可以多次使用,因此将其视为左值更安全。
让我们考虑以下代码:
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",如果它有名字,那么它可以多次使用,因此将其视为左值更安全。