Previous references:
What is the move ?
constructor
The move builder saw the light with the C ++ 11 standard. This constructor is part of what is known as the move syntax, which consists, in general terms, of the move constructor and a new assignment operator:
struct POO
{
// Constructor move
POO(POO&& obj)
{
}
// Asignacion move
POO& operator=(POO && obj)
{
}
};
How it works?
The sintaxis move
aims to avoid the unnecessary copying of large amounts of information. This is achieved, basically, by moving the pointers instead of moving the information contained in them:
struct Objeto
{
int numElems1;
int* ptr1;
int numElems2;
char* ptr2;
// Constructor por defecto
Objeto()
{ /* ... */ }
~Objeto()
{
delete[] ptr1;
delete[] ptr2;
}
// Constructor copia
Objeto(Objeto const& obj)
: numElems1{obj.numElems1},
ptr1{new int[obj.numElems1]},
numElems2{obj.numElems2},
ptr2{new char[obj.numElems2]}
{
std::copy(obj.ptr1,obj.ptr1+numElems1,ptr1);
std::copy(obj.ptr2,obj.ptr1+numElems2,ptr2);
}
// Constructor move
Objeto(Objeto && obj)
: numElems1{obj.numElems1},
ptr1{obj.ptr1},
numElems2{obj.numElems2},
ptr2{obj.ptr2}
{
obj.numElems1 = 0;
obj.ptr1 = nullptr;
obj.numElems2 = 0;
obj.ptr2 = nullptr;
}
};
Objeto FuncionDePrueba();
Objeto a;
Objeto b(a); // Constructor copia;
Objeto c(std::move(a)); // Constructor move
Objeto d(FuncionDePrueba()); // Constructor move
As you can see, invoking the copy constructor involves making memory reservations and copying the data from one instance to another ... while the move approach is dedicated to moving the site pointers (much faster).
A secondary effect of the move syntax is that the original object remains empty or unusable after the operation. Notice how the internal data of obj
is reset in the constructor move . This is why the syntax move only makes sense when the original object is no longer needed.
And what about the assignment operator?
The assignment operator is similar to the constructor but with a fundamental difference ... we are going to modify an object that already exists instead of creating a new one and this forces us to take certain precautions such as cleaning the internal memory before devoting ourselves to moving pointers:
// Asignación tradicional
Objeto& Objeto::operator=(Objeto const& obj)
{
delete[] ptr1;
delete[] ptr2;
numElems1 = obj.numElems1;
ptr1 = new int[numElems1];
std::copy(obj.ptr1,obj.ptr1+numElems1,ptr1);
numElems2 = obj.numElems2;
ptr2 = new char[numElems2];
std::copy(obj.ptr2,obj.ptr2+numElems2,ptr2);
return *this;
}
// Asignacion move
Objeto& Objeto::operator=(Objeto && obj)
{
delete[] ptr1;
delete[] ptr2;
numElems1 = obj.numElems1;
ptr1 = obj.ptr1;
obj.ptr1 = nullptr;
numElems2 = obj.numElems2;
ptr2 = obj.ptr2;
obj.ptr2 = nullptr;
return *this;
}
How to invoke the syntax move ?
This is something that is already explained in the first link I have put as a reference ... I recommend reading to understand the subject.
Is the syntax move the solution to all my problems?
No kidding. The syntax move is neither perfect nor can it always be applied ... if you have objects that do not use dynamic memory you will not get any benefit. In addition, programming this syntax adds more code to the project ... code that you then have to maintain and test ...
Perfect forwarding
This would be the last detail that would be missing in this topic because without it the syntax move is lame and can be a source of errors a bit complicated to understand.
You can find information about it in this another thread