Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I tested the code with VC++14.2 and GCC 5.4.0, both of them output:

A(B &&) 

Why is the output not

A(const B &) 

?

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

like image 498
Caesar Avatar asked Aug 13 '16 12:08

Caesar


People also ask

Why is copy constructor called reference?

A copy constructor defines what copying means,So if we pass an object only (we will be passing the copy of that object) but to create the copy we will need a copy constructor, Hence it leads to infinite recursion. So, A copy constructor must have a reference as an argument.

What is an R value reference?

Rvalue references is a small technical extension to the C++ language. Rvalue references allow programmers to avoid logically unnecessary copying and to provide perfect forwarding functions. They are primarily meant to aid in the design of higer performance and more robust libraries.

What is R Value reference in C ++ 11?

In C++11, however, the rvalue reference lets us bind a mutable reference to an rvalue, but not an lvalue. In other words, rvalue references are perfect for detecting whether a value is a temporary object or not.

In what cases a copy constructor is called?

A copy constructor is called when a new object is created from an existing object, as a copy of the existing object. The assignment operator is called when an already initialized object is assigned a new value from another existing object.


2 Answers

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.

like image 178
Kerrek SB Avatar answered Sep 20 '22 04:09

Kerrek SB


Copy elision is related to A, not being constructed in the get() stack-frame. What happens is that the returned b (that's temporary since "going to die because of return": this is since C++14), is use to construct the copy-elided A in main stack-frame.

And since temporary objects binds r-value references that's what you observed.

like image 31
Emilio Garavaglia Avatar answered Sep 22 '22 04:09

Emilio Garavaglia