#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::movejust 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
valbased on move operation provided bystd::string. E.g.