Reputation: 13
For the code below:
struct Test
{
int size;
Test(int a) { cout << "default" << endl; size = a; }
Test(Test const & t) { cout << "copy" << endl; size = t.size + 1; }
Test(Test && t) { cout << "move" << endl; size = t.size + 1; }
~Test() { cout << "destruct" << endl; }
};
struct Test2
{
int size;
Test2(int a) { cout << "default2" << endl; size = a; }
Test2(Test const & t) { cout << "copy2" << endl; size = t.size + 1; }
Test2(Test && t) { cout << "move2" << endl; size = t.size + 1; }
~Test2() { cout << "destruct2" << endl; }
};
I found the result are different as:
Test t{3}; // default
cout << t.size << endl; // 3
Test move_from_temp = Test(Test(std::move(t))); // move
cout << move_from_temp.size << endl; // 4
Test t{3}; // default
cout << t.size << endl; // 3
Test2 move_from_temp = Test2(Test(std::move(t))); // move, move2, destruct
cout << move_from_temp.size << endl; // 5
However, I expect these two should have the same results. Anyone know the reason for this?
Upvotes: 0
Views: 78
Reputation: 1714
If I run your code the result is slightly different (maybe a typo in your Q?)
Test t{3}; // default
cout << t.size << endl; // 3
Test move_from_temp = Test(Test(std::move(t))); // move
cout << move_from_temp.size << endl; // 4
Test t{3}; // default
cout << t.size << endl; // 3
Test2 move_from_temp = Test2(Test(std::move(t))); // move, move2, destruct
cout << move_from_temp.size << endl; // 5
std::move
is static_cast to an rvalue reference type. It does nothing, only a cast to Test &&
in both versions.
Based on that, in both versions you call the move constructur Test(Test&&)
.
In the first version you are then done because of mandatory "copy elison" https://en.cppreference.com/w/cpp/language/copy_elision
In the second version you call Test2(Test&&)
which cannot be optimized away. The compiler just call the method you provided.
Upvotes: 1