1

Given

#include <iostream>

using namespace std;

struct Test {


public:
    Test() {

        cout << "Default constructor" << endl;
    }

    Test(const Test &) {

        cout << "Copy constructor" << endl;
    }
};

int main() {

    Test && t1 = Test();
}

Why is it that when t1 is initialized, the copy constructor of Test isn't used? From reading reference initialization it appears that object is a temporary which should invoke copy-initialization. Or is this a class type expression? If that is the case can someone define what a class type expression is (I'm having a hard time googling that).

edaniels
  • 708
  • 5
  • 23

1 Answers1

6

Test && t1 = Test(); does not create a reference to a copy, instead Test() produces a temporary object and t1 is bound directly to that temporary (and the temporary's lifetime is extended to the lifetime of the t1).


2) When a named rvalue reference variable is declared with an initializer

Otherwise, if the reference is either rvalue reference or lvalue reference to const:

If object is an xvalue, a class prvalue, an array prvalue, or a function lvalue type that is either T or derived from T, equally or less cv-qualified, then the reference is bound to the value of the initializer expression or to its base subobject.

bames53
  • 86,085
  • 15
  • 179
  • 244
  • Is the object an xvalue or a class prvalue? I thought constructor expressions don't have value associated with them since they don't return anything. – edaniels Oct 15 '14 at 03:33
  • prvalue I believe. All expressions are exactly one of lvalue, xvalue or prvalue. A constructor doesn't `return` anything, but a constructor expression still has the constructed object as its value. The constructor expression is not simply a function call to the constructor, just like using `new` is not simply a function call to the allocation function. The compiler does extra stuff. – bames53 Oct 15 '14 at 03:36
  • But since a prvalue has the properties of an rvalue, I don't see how it could be bound to an lvalue in an example like `Test t` – edaniels Oct 15 '14 at 04:00
  • A declaration `Test t;` doesn't create an rvalue or bind any rvalue to to anything. Perhaps you mean something else? – bames53 Oct 15 '14 at 04:08
  • That should be fine since the default constructor has 0 arguments – edaniels Oct 15 '14 at 04:12
  • `Test t;` is fine, it's just not an expression, and it declares an lvalue variable. No rvalues are involved. – bames53 Oct 15 '14 at 04:15
  • Sorry my bad, what about `Test t = Test()`? That looks like an expression that binds to an lvalue t – edaniels Oct 15 '14 at 04:23
  • @edaniels http://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues – M.M Oct 15 '14 at 04:32
  • @edaniels `Test t = Test();` does do copy construction. However you may not actually see the copy constructor run due to copy elision. [Example](http://coliru.stacked-crooked.com/a/7a9bab2684268b84). See [here](http://en.wikipedia.org/wiki/Copy_elision). – bames53 Oct 15 '14 at 04:54