Pourquoi utilisez-vous std::move quand vous avez && en C++11? [dupliquer]

possible Duplicate:

quelqu'un peut m'expliquer la sémantique du mouvement?

j'ai récemment assisté à un séminaire C++11 et les conseils suivants ont été donnés.

when you have && and you are unsure, you will almost always use std::move

est-ce que quelqu'un pourrait m'expliquer pourquoi vous devriez utiliser std::move par opposition à certaines alternatives et certains cas où vous ne devriez pas utiliser std::move ?

56
demandé sur Community 2013-01-23 22:05:06

4 réponses

tout d'abord, il y a probablement une idée fausse dans la question que je vais aborder:

Chaque fois que vous voyez T&& t dans le code (et T est un type réel, pas un type de modèle), gardez à l'esprit la catégorie de valeur de t est une valeur l(référence), pas une valeur R(temporaire) plus. Il est très déroutant. Le T&& signifie simplement que t est construit à partir d'un objet qui était une valeur 1 , mais t elle-même est une valeur, pas une valeur. Si elle a un nom (dans ce cas, t ) alors c'est une valeur l et ne se déplace pas automatiquement, mais si elle n'a pas de nom (le résultat de 3+4 ) alors c'est une valeur R et va automatiquement se déplacer dans son résultat si elle le peut. Le type (dans ce cas T&& ) n'a presque rien à voir avec la catégorie de valeur de la variable (dans ce cas, une valeur l).

cela étant dit, si vous avez T&& t écrit dans votre code, cela signifie que vous avez une référence à une variable que était un temporaire, et il est correct de détruire si vous voulez. Si vous avez besoin d'accéder à la variable plusieurs fois, vous faites pas voulez std::move à partir de lui, ou bien il perdrait sa valeur. Mais la dernière fois que vous accédez t il est sûr à std::move il est valeur à un autre T si vous le souhaitez. (Et 95% du temps, c'est ce que vous voulez faire). Tout cela s'applique également aux variables auto&& .

1. si T est un type de modèle, T&& est un renvoi à la place, auquel cas vous utilisez std::forward<T>(t) au lieu de std::move(t) la dernière fois. Voir cette question .

80
répondu Mooing Duck 2017-11-27 18:21:47

j'ai trouvé cet article pour être assez éclairant sur le sujet des références rvalue en général. Il mentionne std::move vers la fin. C'est probablement la citation la plus pertinente:

nous devons utiliser std::move , de <utility> -- std::move est un moyen de en disant, "Ok, je te jure, je sais que j'ai une valeur, mais je veux que être une rvalue." std::move ne bouge rien en soi; il tourne juste une lvalue dans une rvalue, de sorte que vous pouvez invoquer le déplacer constructeur.


dites que vous avez un constructeur de mouvements qui ressemble à ceci:

MyClass::MyClass(MyClass&& other): myMember(other.myMember)
{
    // Whatever else.
}

Lorsque vous utilisez l'instruction other.myMember , la valeur retournée est une lvalue. Ainsi le code utilise le copie constructeur pour initialiser this->myMember . Mais comme il s'agit d'un constructeur de déménagement, nous savons que other est un objet temporaire, et donc ses membres. Donc nous voulons vraiment utiliser le plus efficace move constructeur pour initialiser this->myMember . L'utilisation de std::move permet de s'assurer que le compilateur traite other.myMember comme une référence de valeur et appelle le constructeur move, comme vous le souhaitez:

MyClass::MyClass(MyClass&& other): myMember(std::move(other.myMember))
{
    // Whatever else.
}

N'utilisez tout simplement pas std::move sur les objets que vous devez garder autour de vous - les constructeurs de mouvements sont à peu près garantis pour objets passés en eux. C'est pour ça qu'ils ne sont utilisés qu'avec des temporels.

Espère que ça aide!

24
répondu Xavier Holt 2013-01-23 18:34:16

Quand vous avez un objet de type T&& , une rvalue, cela signifie que cet objet est sûr d'être déplacé, comme personne d'autre dépendra de son état interne plus tard.

comme le déménagement ne devrait jamais être plus coûteux que la copie, vous aurez presque toujours envie de le déplacer. Et pour le déplacer, vous devez utiliser la fonction std::move .

Quand devez-vous éviter std::move , même si c'est sans danger? Je ne l'utiliserais pas dans des exemples triviaux, par exemple,:

 int x = 0;
 int y = std::move(x);

de plus, Je ne vois aucun inconvénient. Si cela ne complique pas le code, le déplacement doit être fait chaque fois que possible IMHO.

un autre exemple, où vous ne voulez pas bouger sont les valeurs de retour. La langue garantit que les valeurs de retour sont (au moins) déplacées, donc vous ne devriez pas écrire

return std::move(x); // not recommended

(si vous êtes chanceux, return value optimization hits, ce qui est encore mieux qu'un mouvement opération.)

3
répondu Philipp Claßen 2013-01-23 18:34:07

Vous pouvez utiliser lorsque vous devez transférer le contenu d'un objet quelque part d'autre, sans en faire une copie. Il est également possible pour un objet de prendre le contenu d'un objet temporaire sans en faire une copie, avec std::move.

vérifiez ce lien

1
répondu Rahul Tripathi 2013-01-23 18:30:39