Search code examples
c++move-semanticsstdmove

Move semantics and std::move


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?


Solution

  • 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.