Motion constructor in C ++

5

I am studying the movement constructor in C ++ that receives a reference to an r-value of the type of the class.

The problem is that despite seeing several C ++ Deitel books and several others, I can not find anything of the movement builder , I only have information in a few slides that do not explain it clearly. p>

Would there be a way for you to help me know how to find some information to learn the movement constructor in C ++?

Even in Google, I do not find anything interesting to learn from that builder.

I'll try to be more concrete, you see, it would be about the movement constructor in C ++ 11. It's saying something like:

class C
{
  public:
    C(C&& c) {...}
  //...
}

I know that it is called implicitly when an object is initialized with a reference to value -r which is another object of the same class.

Then in the "little" I have of information, a vector class is exposed without movement of objects (with a copy constructor, a destructor and an assignment operator).

And in the example also comes a builder of movement, allocation of movement and little else, I do not know if this helps you to help me. Here I leave you with more information about the constructor that gives me the example:

Motion builder:

Vector(Vector&& v);

Definition:

//Ctor de movimiento
Vector::Vector(Vector&& v): eltos{v.eltos}, n_eltos{v.n_eltos}
{
 v.eltos = nullptr; //Tras el movimiento se invoca
 v.n_eltos = 0; // al destructor de v.
}

And another one of motion assignment:

Vector& Vector::operator= (Vector&& v) //Parametro no const
{
 delete[] eltos;
 eltos = v.eltos;
 n_eltos = v.n_eltos;
 v.eltos = nullptr; //Tras el movimiento se invocará
 v.n_eltos = 0; //al destructor de v
 return *this;
}
    
asked by ProgrammerJr 17.01.2018 в 12:49
source

1 answer

6

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

    
answered by 17.01.2018 / 13:18
source