107 votes

Réutiliser un conteneur déplacé?

Quelle est la bonne façon de réutiliser un conteneur déplacé?

std::vector container;
container.push_back(1);
auto container2 = std::move(container);

// ver1: Ne rien faire
//container2.clear(); // ver2: "Réinitialiser"
container = std::vector() // ver3: Réinitialiser

container.push_back(2);
assert(container.size() == 1 && container.front() == 2);

D'après ce que j'ai lu dans le brouillon de la norme C++0x ; ver3 semble être la bonne façon, car un objet après un déplacement se trouve dans un

« Sauf indication contraire, de tels objets déplacés doivent être placés dans un état valide mais non spécifié. »

Je n'ai jamais trouvé de cas où il est "autrement spécifié".

Bien que je trouve ver3 un peu indirect et aurait largement préféré ver1, bien que vec3 puisse permettre certaines optimisations supplémentaires, mais d'un autre côté peut facilement conduire à des erreurs.

Ma supposition est-elle correcte?

119voto

Nicol Bolas Points 133791
§17.3.26     état valide mais non spécifié     [defns.valid]

un état d'objet qui n'est pas spécifié sauf que les invariants de l'objet sont respectés et que les opérations sur l'objet se comportent comme spécifié pour son type

[ Exemple : Si un objet x de type std::vector est dans un état valide mais non spécifié, x.empty() peut être appelé inconditionnellement, et x.front() peut être appelé uniquement si x.empty() retourne false. — fin de l'exemple ]

Par conséquent, l'objet est vivant. Vous pouvez effectuer toute opération qui ne nécessite pas de précondition (à moins que vous ne vérifiiez d'abord la précondition).

clear, par exemple, n'a aucune précondition. Et cela retournera l'objet dans un état connu. Il suffit donc de le vider et de l'utiliser normalement.

21voto

Grizzly Points 11329

L'objet étant dans un état valide, mais non spécifié signifie essentiellement que, bien que l'état exact de l'objet ne soit pas garanti, il est valide et en tant que tel, les fonctions membres (ou non membres) sont garanties de fonctionner tant qu'elles ne dépendent pas de l'objet ayant un certain état.

La fonction membre clear() n'a aucune précondition concernant l'état de l'objet (autre que d'être valide, bien sûr) et peut donc être appelée sur des objets déplacés. En revanche, par exemple front() dépend du conteneur qui n'est pas vide et ne peut donc pas être appelée, car il n'est pas garanti d'être non vide.

Par conséquent, tant ver2 que ver3 devraient tous les deux être corrects.

-10voto

Ben Voigt Points 151460

Je ne pense pas que vous puissiez faire quoi que ce soit avec un objet déplacé (à part le détruire).

Ne pouvez-vous pas utiliser swap à la place, pour profiter de tous les avantages du déplacement mais laisser le conteneur dans un état connu ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X