Caesar Caesar - 3 months ago 7
C++ Question

c++- why is r-value reference constructor called instead of const l-value reference constructor at return statement

#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();
}


I test the code by VC++14.2 and GCC 5.4.0, both of the output are

A(B &&)


Why is the output not

A(const B &)


?

Does this code have relation with
copy elision
? (But A and B are different type,
copy elision
should not work here.)

Answer

The return-as-rvalue rules changed in response to the review before publication of C++14. The change was added late in the process and is captured by CWG Issue 1579, that amends 12.8/32 with the wording:

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

This means that returning any local variable now considers the object designated by that variable as if it were an rvalue first (trying again if overload resolution fails).

Since the CWG issue was accepted as a defect in the language, compilers may implement this new rule even in "C++11 mode". The point of a defect is that "it was always meant to work that way", so this isn't strictly speaking a change between C++11 and C++14, but rather, the meaning of C++11 was modified in 2014.