web-dev-qa-db-fra.com

Que puis-je faire avec un objet déplacé?

La norme définit-elle précisément ce que je peux faire avec un objet une fois qu'il a été déplacé? Je pensais que tout ce que vous pouvez faire avec un objet déplacé est de le détruire, mais cela ne serait pas suffisant.

Par exemple, prenez le modèle de fonction swap tel que défini dans la bibliothèque standard:

template <typename T>
void swap(T& a, T& b)
{
    T c = std::move(a); // line 1
    a = std::move(b);   // line 2: assignment to moved-from object!
    b = std::move(c);   // line 3: assignment to moved-from object!
}

De toute évidence, il doit être possible d'affecter aux objets déplacés, sinon les lignes 2 et 3 échoueraient. Que puis-je faire d'autre avec les objets déplacés? Où puis-je trouver ces détails dans la norme?

(Soit dit en passant, pourquoi est-ce T c = std::move(a); au lieu de T c(std::move(a)); à la ligne 1?)

132
fredoverflow

Les objets déplacés existent dans un état non spécifié, mais valide. Cela suggère que bien que l'objet ne soit plus capable de faire grand-chose, toutes ses fonctions membres devraient toujours présenter un comportement défini - y compris operator= - et tous ses membres dans un état défini - et il nécessite toujours la destruction. La norme ne donne pas de définitions spécifiques car elle serait unique à chaque UDT, mais vous pourriez être en mesure de trouver des spécifications pour les types standard. Certains conteneurs similaires sont relativement évidents - ils déplacent simplement leur contenu et un conteneur vide est un état valide bien défini. Les primitives ne modifient pas l'objet déplacé.

Note latérale: Je crois que c'est T c = std::move(a) de sorte que si le constructeur de déplacement (ou le constructeur de copie si aucun déplacement n'est fourni) est explicite, la fonction échouera.

52
Puppy

17.6.5.15 [lib.types.movedfrom]

Les objets de types définis dans la bibliothèque standard C++ peuvent être déplacés de (12.8). Les opérations de déplacement peuvent être spécifiées explicitement ou générées implicitement. Sauf indication contraire, ces objets déplacés doivent être placés dans un état valide mais non spécifié.

Lorsqu'un objet est dans un état non spécifié, vous pouvez effectuer n'importe quelle opération sur l'objet qui n'a pas de conditions préalables. S'il y a une opération avec des conditions préalables que vous souhaitez effectuer, vous ne pouvez pas effectuer directement cette opération parce que vous ne savez pas si l'état non spécifié de l'objet satisfait aux conditions préalables.

Exemples d'opérations qui généralement n'ont pas de conditions préalables:

  • destruction
  • affectation
  • observateurs const tels que get, empty, size

Exemples d'opérations qui généralement ont des conditions préalables:

  • déréférencement
  • pop_back

Cette réponse apparaît maintenant au format vidéo ici: http://www.youtube.com/watch?v=vLinb2fgkHk&t=47m10s

107
Howard Hinnant