Je pense que c'est plus une question de philosophie que de la technique :)
La question sous-jacente est quelle est la différence entre les Déplacer et Copier. Je ne vais pas sauter dans technique / standardista de la langue, nous allons le faire simplement:
- Copie: créer un autre objet identique (ou au moins, qu'il convient de comparer l'égalité)
- Déplacer: prendre un objet et de le mettre dans un autre endroit
Comme vous l'avez dit, il est possible de mettre en œuvre Déplacer en terme de Copie: créer une copie dans le nouvel emplacement et jeter l'original. Il existe toutefois deux questions. L'un est de la performance, le deuxième est sur les objets utilisés pour le RAII: lequel des deux doit avoir la propriété ?
Un bon constructeur de Déplacement résout le 2 questions:
- Il est clair quel est l'objet qui a la propriété: le nouveau, depuis l'origine sera rejeté
- Il est donc inutile de copier les ressources souligné, ce qui permet une plus grande efficacité
L' auto_ptr
et unique_ptr
sont une très bonne illustration.
Avec un auto_ptr
vous avez vissé Copie sémantique: l'original et la copie, ne compare pas l'égalité. Vous pouvez l'utiliser pour son Déplacement sémantique, mais il y a un risque que vous allez perdre de l'objet pointé quelque part.
D'autre part, l' unique_ptr
, c'est exactement cela: il garantit l'unicité du propriétaire de la ressource, donc d'éviter la copie et l'inévitable problème de suppression qui va suivre. Et la pas de copie est garanti au moment de la compilation trop. Par conséquent, il est approprié dans des contenants tant que vous n'essayez pas d'avoir copie de l'initialisation.
typedef std::unique_ptr<int> unique_t;
typedef std::vector< unique_t > vector_t;
vector_t vec1; // fine
vector_t vec2(5, unique_t(new Foo)); // Error (Copy)
vector_t vec3(vec1.begin(), vec1.end()); // Error (Copy)
vector_t vec3(make_move_iterator(vec1.begin()), make_move_iterator(vec1.end()));
// Courtesy of sehe
std::sort(vec1.begin(), vec1.end()); // fine, because using Move Assignment Operator
std::copy(vec1.begin(), vec1.end(), std::back_inserter(vec2)); // Error (copy)
De sorte que vous pouvez utiliser unique_ptr
dans un récipient (contrairement à auto_ptr
), mais un certain nombre d'opérations sera impossible parce qu'ils impliquent la copie dont le type ne prend pas en charge.
Malheureusement Visual Studio peut être assez laxiste dans l'application de la norme et a également un certain nombre d'extensions que vous auriez besoin de les désactiver pour assurer la portabilité du code... de ne pas l'utiliser pour vérifier le niveau :)