Chapitre 20 : Déplacement

EXEMPLE
#include<iostream>
#include<string>

using namespace std;

int main(){
  string s;
  string t[10];
  int i, l=0;
  for (int i=0;i<10; i++){
    cin >> s;
    if (s.size() > 0 && s[0] == 'a')
      t[l++] = std::move(s); //ici appel à l'opérateur de déplacement (sting::operator=(string&& s))
                             //et pas l'opérateur d'affectation (string::operator=(const string& s))
  }
  return 0;
}

On peut surcharger dans une classe A :

  • Le constructeur A par A(A&& s) (constructeur par déplacement)
  • L'opérateur = par A::operator=(A&& s) (l'opérateur de déplacement)

On peut les invoquer grâce à std::move

EXEMPLE
A obj{std::move(exp)}
obj = std::move(exp);

En général si on a besoin d'explicitement ecrire l'opérateur d'affectation, le destructeur, le constructeur par copie (règle des 3)

Alors il est parfois utile d'écrire

  • l'opérateur de déplacement
  • constructeur par déplacement

(règle des 5)


EXEMPLE AVEC HERITAGE
class M{...};
class A{...};

class F : public M{
  A attr;
  F(F&& s) : M(std::move(s)), attr{std::move(s.attr)}{
    ...
  }
  const F& operator=(F&& s){
    this->M::operator=(std::move(s));
    this->attr = std::move(s.attr);
};
AUTRE EXEMPLE
class A{//tableau de int de taille 100
  int* t = nullptr;
  A(){
    t = malloc(100);
  }
  A(const A& s){
    if (s.t == nullptr) return;
    t = malloc(100);
    for (int i=0; i<100; i++){
      t[i] = s.t[i];
    }
  }
  const A& operator=(const A& s){
    if (this == &s) return;
    if (s.t == nullptr){
      if (this->t != nullptr){
        free(this->t);
        this->t = nullptr;
      }
    }
    if (s.t != nullptr){
      if (this->t == nullptr)
        this->t = malloc(100);
      for (int i=0; i<100; i++)
        t[i] = s.t[i];
    }
    return *this;
  }
  ~A(){
    if (this->t != nullptr) free(this->t)
  }
  const A& operator=(A&& s){
    if (this == &s) return;
    if (this->t != nullptr) free(this->t);
    this->t = s.t;
    s.t = nullptr;
    return *this;
  }