I have a general question about move semantics. Yesterday I just played around to get more comfortable with this topic. Here I added copy and move constructor operators, that simply log to the console:
#include <iostream>
class Test {
public:
const char* value = "HI";
Test(){
std::cout << "Default Constructed\n";
}
Test(Test &&source) {
std::cout << "Move Constructed\n";
}
Test(const Test &source) {
std::cout << "Copy Constructed\n";
}
};
Now when I call
void showMe(Test&& test) {
std::cout << test.value;
}
int main() {
Test test1;
// Test test2{test1};
showMe(std::move(test1));
return 0;
}
The console logs out:
> Default Constructed
> HI
Which is clear to me, since we are just moving the ownership to showMe
. But why wasn't the Test's move constructor operator be called?
But now, if I change showMe
function into
void showMe(Test test) {
std::cout << test.value;
}
the console shows:
> Default Constructed
> Move Constructed
> HI
So my question is, why was the Move constructor operator not executed in the first case, but in the second? I usually thought in the first case, the Test's move operator should execute. What are the differences between those two cases mentioned?
CodePudding user response:
But why wasn't the Test's move constructor operator be called?
Because you keep operating on the same object via a reference to an rvalue. No new object is being constructed, hence no constructor is necessary.
You could conceivably keep passing that reference down, just like you can do with a regular reference or a reference to const - the very nature of references is that they're not objects.
In your second example, the parameter to the function is a value, and in order to construct that value, the second constructor needs to fire.
CodePudding user response:
In the first place you pass a reference. Therefore, no new object needs to be created.
CodePudding user response:
in void showMe(Test test) formal argument expect passed by value so that is the reason Move Constructed\ gets called (Passing by value means that the parameter is copied into the function. That calls the move constructor ) .in second case void showMe(Test&& test) formal argument expect pass by reference hence no new object created , no constructor gets called