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

Cae*_*sar 35 c++ return implicit-conversion

#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();
}
Run Code Online (Sandbox Code Playgroud)

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

A(B &&)
Run Code Online (Sandbox Code Playgroud)

为什么输出不是

A(const B &)
Run Code Online (Sandbox Code Playgroud)

这段代码与此有何关系copy elision?(但A和B是不同的类型,所以copy elision不应该在这里工作)

Ker*_* SB 29

响应于在C++ 14发布之前的评论,返回的右值规则发生了变化.该变更是在流程的后期添加的,并由CWG Issue 1579捕获,其修改为12.8/32,措辞如下:

或者当一个return语句中的表达式是一个(可能带括号的)id-expression,它命名一个具有在体内声明的自动存储持续时间的对象

这意味着返回任何局部变量现在将该变量指定的对象视为首先是rvalue(如果重载决策失败则再次尝试).

由于CWG问题被接受为语言中的缺陷,编译器甚至可以在"C++ 11模式"中实现这一新规则.缺陷的一点是"它始终意味着以这种方式工作",所以这并不是严格意义上说C++ 11和C++ 14之间的变化,而是修改了C++ 11的含义在2014年.


Emi*_*lia 5

复制省略与A相关,而不是在get()堆栈帧中构造.会发生什么事情是返回的b(那是因为"因为返回而死"的临时性:这是因为C++ 14),用于A在主堆栈框架中构造复制删除.

并且因为临时对象绑定了您观察到的r值引用.