右值重载? [复制]

Posted

技术标签:

【中文标题】右值重载? [复制]【英文标题】:Overloading for rvalue? [duplicate] 【发布时间】:2019-05-24 10:05:02 【问题描述】:

下面是演示问题的代码:

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&& 类型的变量和这个类型的重载,但是这个重载没有被调用。

【问题讨论】:

右值引用被认为是左值。您需要std::move 参考。 【参考方案1】:

引用并不是这样工作的。你的论点rvalue_ref,尽管它的类型,是一个左值表达式。您必须再次执行 std::move 才能使其成为右值。

类型和值类别是两个独立的东西,很难记住命名右值引用类型对象的表达式不会自动成为右值表达式。

同时考虑:

void foo(T&& ref)

   bar(ref);             // lvalue arg
   bar(std::move(ref));  // rvalue arg

cppreference.com's "Value categories" article上也提到了这一点:

即使变量的类型是右值引用,由其名称组成的表达式也是左值表达式

【讨论】:

但这不会破坏函数重载解析的任何规则吗?看起来很奇怪,没有为 T 类型的变量调用 func(T)。 @beginpluses 是的。这里没有任何问题,这就是 C++ 的工作方式。我承认价值类别可能会令人困惑,因为它们是“不可见的”。我更希望看到一个 IDE,它可以在鼠标悬停时向您显示某些表达式的值类别,但我认为目前还没有这样的东西。 "对于 T 类型的变量" 你应该忘记变量并考虑表达式。在我的示例中,您传递给ref 的表达式是T 类型,而不是T&& 类型。这就是它的工作原理。重载没有问题,只有理解表达式。【参考方案2】:

这是完全合理的行为——右值引用是 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

【讨论】:

以上是关于右值重载? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

移动选定的构造函数而不是复制。 [参考标准]

右值引用重载 && 运算符

是否有任何理由使用右值引用重载运算符?

将多个右值和左值传递给函数而不创建重载

为 const 引用和 rvalue 引用编写重载

书中“右值”和“右值引用”之间的混淆