Reputation: 487
What is the correct way of using or creating a move constructor?
Here is an example:
class Example
{
public:
Example( int && p_Number,
bool && p_YesNo,
std::string && p_String ) : // Error here
Number( p_Number ),
YesNo( p_YesNo ),
String( p_String )
{
};
private:
int Number;
bool YesNo;
std::string String;
std::vector< unsigned char > Vector;
};
void ShowExample( void )
{
Example ExampleA( 2013,
true,
"HelloWorld" // Why won't it work?
);
};
I've shown the errors in the comment.
Edit: *Okay, I am now sure what I have is not a move constructor. So, can I write one?*
Upvotes: 2
Views: 3007
Reputation: 103751
First of all, there is no reason to write a move constructor for that class. The compiler generated one will do just fine. But if you were to write it, it might look something like this:
Example(Example && rhs)
:Number(rhs.Number)
,YesNo(rhs.YesNo)
,String(std::move(rhs.String))
,Vector(std::move(rhs.Vector))
{}
You can, if you want, for consistency, call std::move
on the int
and the bool
, but you won't gain anything from it.
For that other constructor, with all the arguments, the simplest thing to do is this:
Example(int p_Number, bool p_YesNo, std::string p_String)
:Number(p_Number)
,YesNo(p_YesNo)
,String(std::move(p_String))
{}
In response to your comment below:
A move constructor is invoked whenever you try to construct an object with an R-value of the same type as the only constructor argument. For example, when an object is returned by value from a function, that is an R-value, although often in that case, copying and moving is skipped altogether. A case where you can create an R-value is by calling std::move
on an L-value. For example:
Example ex1(7, true, "Cheese"); // ex1 is an L-value
Example ex2(std::move(ex1)); // moves constructs ex2 with ex1
Upvotes: 11
Reputation: 254751
A move constructor takes an rvalue reference to another object of the same type, and moves the other object's resources to the new object, for example:
Example(Example && other) :
Number(other.Number), // no point in moving primitive types
YesNo(other.YesNo),
String(std::move(other.String)), // move allocated memory etc. from complex types
Vector(std::move(other.Vector))
{}
Although, unless your class is itself managing resources, there's no point in writing this at all - the implicit move constructor will do exactly the same thing as the one I wrote.
Upvotes: 5