【问题标题】:Automatic move from local variables when variable is rvalue reference当变量是右值引用时从局部变量自动移动
【发布时间】:2020-05-20 12:14:44
【问题描述】:

根据cppreference,在return语句中,本地右值引用应该从C++20中移出:

从局部变量和参数自动移动

  • 如果表达式是一个(可能带括号的)id 表达式,它命名一个变量,其类型为

  • 非易失性对象类型或 对对象类型的非易失性右值引用 (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!。这是尚未在编译器中实现的东西吗?还是我误会了什么?

【问题讨论】:

  • 这个例子中有两个类的目的是什么?
  • @DanielLangr:不能避免 NRVO。
  • 检查 here,自 19.24 版本起仅在 MSVC 上可用 - DR:隐式移动更多本地对象和右值引用
  • @rafix07 这基本上是一个答案。
  • @rafix07:谢谢,很高兴知道那张桌子!

标签: c++ c++20


【解决方案1】:

这是尚未在编译器中实现的东西吗?

Not implemented yet(查找 P1825),您正确理解了规则。但让我们通过它来确定。这里的具体标准文字在[class.copy.elision]/3

隐式可移动实体是一个自动存储持续时间的变量,它可以是非易失性对象或对非易失性对象类型的右值引用。在以下复制初始化上下文中,可能会使用移动操作而不是复制操作:

  • 如果return ([stmt.return]) 或co_­return ([stmt.return.coroutine]) 语句中的表达式 是(可能带括号的)id-表达式 命名一个隐式可移动实体,该实体在主体parameter-declaration-clause 的最内层封闭函数或lambda 表达式中声明,或
  • 如果 throw-expression 的操作数是 [...]

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

【讨论】:

    猜你喜欢
    • 2020-02-16
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    • 2012-04-15
    • 2011-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多