右值重载?
Overloading for rvalue?
下面是演示问题的代码:
class X {};
X x;
X&& rvalue_ref = std::move(x);
static_assert(std::is_same<decltype(rvalue_ref), X&&>::value, "Different types"); //To be sure that type is X&&
void func(X&) {
cout << "lvalue reference";
}
void func(X&&) {
cout << "rvalue reference";
}
int main() {
func(rvalue_ref);
}
输出:
lvalue reference
能解释一下原因吗?我们有一个 X&& 类型的变量和一个该类型的重载,但未调用该重载。
参考文献并不是那样有效的。你的参数 rvalue_ref
,尽管它的类型,是一个 左值表达式 。您必须再次执行 std::move
才能使其成为右值。
类型和值类别是两个独立的事物,很难记住命名 右值引用 类型对象的表达式不会自动成为右值表达式。
另请考虑:
void foo(T&& ref)
{
bar(ref); // lvalue arg
bar(std::move(ref)); // rvalue arg
}
cppreference.com's "Value categories" article上也提到了这个:
Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression
这是完全合理的行为 - 右值引用在 C++ 中是左值。这意味着获得输出
rvalue reference
你必须这样使用 std::move
:
int main() {
func(std::move(rvalue_ref));
}
这在将参数传递给函数时尤其容易混淆。例如,要将参数作为右值传递,您必须使用 std::move
:
void foo(bar &&baz) {
function_taking_rvalue_reference(std::move(baz));// <--- this move is necessary
}
下面是演示问题的代码:
class X {};
X x;
X&& rvalue_ref = std::move(x);
static_assert(std::is_same<decltype(rvalue_ref), X&&>::value, "Different types"); //To be sure that type is X&&
void func(X&) {
cout << "lvalue reference";
}
void func(X&&) {
cout << "rvalue reference";
}
int main() {
func(rvalue_ref);
}
输出:
lvalue reference
能解释一下原因吗?我们有一个 X&& 类型的变量和一个该类型的重载,但未调用该重载。
参考文献并不是那样有效的。你的参数 rvalue_ref
,尽管它的类型,是一个 左值表达式 。您必须再次执行 std::move
才能使其成为右值。
类型和值类别是两个独立的事物,很难记住命名 右值引用 类型对象的表达式不会自动成为右值表达式。
另请考虑:
void foo(T&& ref)
{
bar(ref); // lvalue arg
bar(std::move(ref)); // rvalue arg
}
cppreference.com's "Value categories" article上也提到了这个:
Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression
这是完全合理的行为 - 右值引用在 C++ 中是左值。这意味着获得输出
rvalue reference
你必须这样使用 std::move
:
int main() {
func(std::move(rvalue_ref));
}
这在将参数传递给函数时尤其容易混淆。例如,要将参数作为右值传递,您必须使用 std::move
:
void foo(bar &&baz) {
function_taking_rvalue_reference(std::move(baz));// <--- this move is necessary
}