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

#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.0testing了代码,两者都输出:

 A(B &&) 

为什么输出不是

 A(const B &) 

这段代码和copy elision有什么关系吗? (但是A和B是不同的types,所以copy elision不应该在这里工作)

作为右值的规则在C ++ 14发布之前就被修改了。 这一变化在这个过程中很晚才join,并由CWG Issue 1579收录 ,修改为12.8 / 32的措词:

或者当return语句中的expression式是一个(可能为括号的) id-expression式 ,该expression式在主体中声明具有自动存储持续时间的对象

这意味着返回任何局部variables现在都将该variables指定的对象视为首先右值(如果重载parsing失败,则再次尝试)。

由于CWG问题被认为是语言上的缺陷,编译人员甚至可以在“C ++ 11模式”下实施这一新规则。 缺点在于“总是意味着要这样工作”,所以这并不是严格意义上的C ++ 11和C ++ 14之间的变化,而是C ++ 11的意义被修改了在2014年。

复制elision与A相关,而不是在get()堆栈中构造。 会发生什么是返回的b (这是因为“因为返回而死”的暂时的:这是自C ++ 14以来),用于在主栈帧中构造复制消失的A

而且由于临时对象绑定了r值引用,这就是你所观察到的。