为什么在这种情况下调用右值引用构造函数?

Why is r-value reference constructor called in this case?

#include<iostream>
using namespace std;

struct B{};

struct A
{
    A(const B &)
    {
        cout<<"A(const B &)"<<endl;
    }
    A(B &&)
    {
        cout<<"A(B &&)"<<endl;
    }
};

A get()
{
    B b;
    return b;
}

int main()
{
    get();
}

我用 VC++14.2 和 GCC 5.4.0 测试了代码,它们都输出:

A(B &&)

为什么输出不是

A(const B &)

?

这段代码和copy elision有关系吗? (但是A和B是不同的类型,所以copy elision这里应该不行)

return-as-rvalue 规则已更改,以响应 C++14 发布前的审查。更改是在过程的后期添加的,并由 CWG Issue 1579 捕获,用措辞修改 12.8/32:

or when the expression in a return statement is a (possibly parenthesized) id-expression that names an object with automatic storage duration declared in the body

这意味着 returning 任何局部变量现在首先将由该变量指定的对象视为右值(如果重载解析失败,则重试)。

由于 CWG 问题被认为是语言中的一个缺陷,编译器甚至可以在 "C++11 mode" 中实施这一新规则。缺陷点是"it was always meant to work that way",所以严格来说这不是C++11和C++14之间的变化,而是C++11的含义在2014年被修改了

复制省略与 A 相关,不是在 get() 堆栈框架中构造的。 发生的事情是返回的 b(这是临时的,因为 "going to die because of return":这是从 C++14 开始的),用于在主堆栈框架中构造复制省略的 A

并且由于临时对象绑定了 r 值引用,这就是您观察到的情况。