I am trying to better understand how C++ constructors/initialization work. Case 2 and 5 below are confusing me.
Test case2 = Test();
Reading this, I would think it would default construct an instance of Test
and copy it into case2
. However, only the default constructor is invoked.
Test&& case5 = Test();
adds to my confusion. If Test() is being bound to an rvalue reference, would that not mean Test() is producing an rvalue? If that's the case, shouldn't case2 invoke the default constructor, then the move constructor?
Is case 3 then producing a prvalue that we're calling std::move on (to an xvalue)? If that's the case, shouldn't case 3 and 2 behave the same (default construct an object, then use move constructor).
#include <iostream>
using namespace std;
class Test {
int x;
public:
Test() : x(0) {
cout << "DEFAULT CONSTRUCTOR CALLED" << endl;
}
Test(int v_x) : x(v_x) {
cout << "PARAMETER CONSTRUCTOR CALLED" << endl;
}
Test(Test& other) : x(other.x) {
cout << "COPY CONSTRUCTOR CALLED" << endl;
}
Test(Test&& other) : x(other.x) {
cout << "MOVE CONSTRUCTOR CALLED" << endl;
}
};
int main()
{
cout << "CASE 1: " << endl;
Test case1; // calls default constructor
cout << "CASE 2: " << endl;
Test case2 = Test(); // calls default constructor
cout << "CASE 3: " << endl;
Test case3 = std::move(Test()); // calls default constructor, then move constructor
cout << "CASE 4: " << endl;
Test case4 = case3; // calls copy constructor
cout << "CASE 5: " << endl;
Test&& case5 = Test(); // calls default constructor
return 0;
}