当变量是右值引用时自动从局部变量移动

Automatic move from local variables when variable is rvalue reference

根据 cppreference,在 return 语句中,局部右值引用应该从 C++20 中移除:

Automatic move from local variables and parameters

  • If expression is a (possibly parenthesized) id-expression that names a variable whose type is either

  • a non-volatile object type or a non-volatile rvalue reference to object type (since C++20)

我尝试了第二个要点 (godbolt):

#include <cstdio>

struct Foo {};

struct Bar {
    Bar() = default;

    Bar(const Foo &) {
        printf("copy!\n");
    }
    Bar(Foo &&) {
        printf("move!\n");
    }
};

Bar foo() {
    Foo f;
    Foo &&rf = static_cast<Foo &&>(f);
    return rf;
}

int main() {
    foo();
}

我预计该程序会打印 move!。但实际上,clang 和 gcc 都打印 copy!。这是编译器尚未实现的东西吗?还是我误解了什么?

Is this something which haven't been implemented yet in compilers?

Not implemented yet (look for P1825), you understand the rule correctly. But let's go through it to be sure. The specific standard text here is in [class.copy.elision]/3:

An implicitly movable entity is a variable of automatic storage duration that is either a non-volatile object or an rvalue reference to a non-volatile object type. In the following copy-initialization contexts, a move operation might be used instead of a copy operation:

  • If the expression in a return ([stmt.return]) or co_­return ([stmt.return.coroutine]) statement is a (possibly parenthesized) id-expression that names an implicitly movable entity declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, or
  • if the operand of a throw-expression is a [...]

rf 是对 Foo(非易失性对象类型,检查)的右值引用(检查),这使其成为隐式可移动实体。在 return rf; 中,这是一个 id 表达式 ,它命名一个在函数体 (check) 中声明的隐式可移动实体 (check)。所以,我们移动而不是复制。