返回类型中 && 和没有引用之间的区别

Difference between && and no ref in return type

本文关键字:之间 引用 区别 返回类型      更新时间:2023-10-16

当返回类型显式声明为右值与无引用时,行为是否有区别? 根据下面的示例,似乎没有任何区别。

#include <iostream>
#include <vector>
using namespace std;
struct A {
    A(int x) : x_(x) {}
    A(A&&) = default;  // VC12 hasn't implemented default move
    A(const A&) = delete;
    A& operator=(A&&) = default;
    A& operator=(const A&) = delete;
    vector<int> x_;
};
struct B{
    B(int x) : a_(x) {}
    A&& foo1() { return move(a_); }  // explicitly declared as rvalue
    A foo2() { return move(a_); }    // no ref
    A a_;
};
int main() {
    B b1(7);
    A a1 = b1.foo1();
    B b2(7);
    A a2 = b2.foo2();       
    cout << a1.x_.size() << ' ' << a2.x_.size() << endl;
    cout << b1.a_.x_.size() << ' ' << b2.a_.x_.size() << endl;
    return 0;
}

这个例子是由Ideone的C++14编译器(不确定确切的版本,我怀疑是GNU 5.1)和VC12(Visual Studio 2013)编译的。 唯一的细微区别是 VC12 需要显式移动实现。

编辑:一个相关的SO帖子说,这两个功能最终做同样的事情。 但是,"在许多情况下,它允许编译器执行复制省略并省略对返回类型的移动构造函数的调用,如C++11标准第12.8/31段所允许的那样"。 "Copy elision 允许编译器直接在对象中创建函数的返回值。

问题 1:显式调用 move 时,仍应进行复制省略,对吗?

问题2:当 move 被显式调用左值(所以是必需的调用)时,A&& 和 A 意味着相同的行为。 如果未显式调用 move,这意味着编译器执行复制省略,则 A 应该是唯一的返回类型。 结合上面的两个场景,我是否可以得出结论,返回类型A&&没有用,只会增加混乱?

A&& foo1() { return move(a_); }
A foo2() { return move(a_); }
  • foo1返回一个(右值)引用。
  • foo2构造一个
  • 对象A 移动构造函数。