是否有任何理由将返回值捕获为右值引用?

Ste*_*mer 5 c++ move c++11

我有一个只能移动的 structFoo和一个函数Foo get();

如果我想以get可变的方式捕获 的返回值,我有两个选择:

  • 按值 ( Foo)
  • 通过右值引用 ( Foo&&)

当我通过 rvalue-reference 捕获时,我创建了一个左值,就像按值捕获一样。

我很难看出不同选项之间的关系?

  • 这两者有什么区别吗?

工作示例:

#include <iostream>

struct Foo
{
    Foo(std::string s) : s(std::move(s)) {}
    Foo(Foo&& f)       : s(std::move(f.s)) {}

    Foo(const Foo&) = delete;
    Foo& operator=(const Foo&) = delete;

    std::string s;
};

Foo get()
{
    return Foo { "hello" };
}

int main()
{
    // capture return value as l-value
    Foo lv1 = get();

    // move into another lvalue
    Foo lv2 = std::move(lv1);
    std::cout << lv2.s << '\n';

    // capture return value as r-value reference
    Foo&& rv1 = get();

    // move into another lvalue
    Foo lv3 = std::move(rv1);
    std::cout << lv3.s << '\n';

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Nic*_*las 5

Foo lv1 = get();
Run Code Online (Sandbox Code Playgroud)

这要求它Foo是可复制/可移动的。

Foo&& rv1 = get();
Run Code Online (Sandbox Code Playgroud)

这不是(至少,就这一行代码而言不是; 的实现get可能仍然需要一个)。

尽管允许编译器将返回值的副本省略到变量中,但这种形式的副本初始化仍然需要存在可访问的复制或移动构造函数。

所以如果你想对类型施加尽可能少的限制Foo,你可以存储一个&&返回值。

当然,C++17 改变了这个规则,所以第一个不需要复制/移动构造函数。