将左值绑定到右值引用,移动变量和函数返回

binding of lvalue into rvalue reference move ctor and return of function

本文关键字:变量 移动 函数 返回 引用 绑定      更新时间:2023-10-16

据我所知,将左值绑定到右值引用是无效的。其次,左值表达式可以通过以下事实来识别:它可以以地址操作符(&)

作为前缀

如果这两个句子用下面的代码是正确的,我就有点麻烦了:

 #include<iostream>
struct Foo
{
    Foo(Foo&& other)
    {
        std::cout << "move ctor called";
    }
    Foo(const Foo& other)
    {
        std::cout << "copy ctor called";
    }
    Foo(){}
};
Foo return_foo()
{
    Foo f;
    return f;
}

void main()
{  
    Foo f = return_foo(); // Move ctor is called, but return_foo() is a lvalue ?? 
    std::cin.ignore();    
}

我哪里错了

return_foo()返回一个右值(因为它返回未命名的临时对象)。引用自§3.10/1,强调我的:

一个右值("纯"右值)是一个非xvalue的右值。(示例:调用返回类型不是a的函数的结果Reference是一个右值。字面量的值,如12、7.3e5或True也是一个右值。-end example]

有一个特殊的规则允许将临时值作为右值返回,也就是说,以下是等效的-显式的"我不再需要这个"版本:

T foo()
{
  T t(a, b, ...); // constructed somehow
  /* ... */
  return std::move(t);
}
int main()
{
  T t = foo(); // we can move-construct this
}

…隐式版本:

T foo()
{
  T t(a, b, ...);
  /* ... */
  return t;  // implicitly allow moving
}

所有这些都发生在返回值优化之后。这意味着按值返回在很多情况下实际上是非常有效的。