#include <iostream>
using namespace std;
class Test {
public:
Test(string value){
cout<<"Ctor "<<value<<endl;
_val=value;
}
Test( Test&& mv): _val(mv._val)
{
mv._val=string();
cout<<"Mv constructor"<<endl;
}
string& get()
{
return this->_val;
}
private:
string _val;
};
void print(Test&& t)
{
cout<<"Stampa val is "<<t.get()<<endl;
}
int main()
{
Test a{"ciao"};
print(move(a));
cout<<"Val of a is "<<a.get()<<endl;
print(Test("test"));
return 0;
}
The output of this is (adding line numbers to stdout):
Ctor ciao
Stampa val is ciao
Val of a is ciao
Ctor test
Stampa val is test
Why at line 2 in main the mv semantic is not called? I might understand at line four there is an optimisation so the constructor only is called but, I can't explain the first move. Any ideas?
std::move
just converts argument to rvalue (which could be moved later), it doesn't perform move operation itself. The converted rvalue is bound to the reference parametert
, so the move constructor isn't invoked in this case.Move constructor is typically called to initialize an object, it won't be called in reference binding (it's true for lvalue-reference too). If you change the parameter to be passed by-value, move constructor would be used (to initialize the parameter). E.g.
LIVE
BTW: Even after change to pass-by-value
print(Test("test"));
doesn't invoke move constructor because of copy elision.BTW2: In the move constructor it's better to move initialize data member
val
based on move operation provided bystd::string
. E.g.