75 votes

en C++11 pourquoi utiliser std::move lorsque vous avez &&

Double Possible:
Quelqu'un peut-il expliquer la sémantique de déplacement à moi?

J'ai récemment assisté à une de C++11 séminaire et à la suite de friandise de conseils ont été donnés.

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

Pouvait-on m'expliquer pourquoi vous devriez l'utiliser std::move contrairement à certaines solutions de rechange et certains cas, lorsque vous ne devriez pas utiliser std::move?

112voto

Mooing Duck Points 27497

Tout d'abord, il y a probablement une idée fausse à 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 valeur de la catégorie d' t est une lvalue(de référence), pas une rvalue(temporaire) de plus. Il est très déroutant. L' T&& signifie simplement que t peut être construit à partir d'un objet qui a une valeur r 1, mais t lui-même est une lvalue, pas une rvalue. Si il a un nom (dans ce cas, t) alors c'est une lvalue et de ne pas déplacer automatiquement, mais si elle n'a pas de nom (à la suite d' 3+4) alors c'est une rvalue et sera automatiquement déplacer en conséquence s'il peut. Le type (dans ce cas - T&&) a presque rien à voir avec la valeur de la catégorie de la variable (dans ce cas, une lvalue).

Cela étant dit, si vous avez T&& t il est écrit dans le code, cela signifie que vous avez une référence à une variable qui est temporaire, et il est ok pour détruire si vous le souhaitez. Si vous avez besoin d'accéder à la variable plusieurs fois, vous n'avez pas souhaitez std::move à partir d'elle, sinon elle perdra de sa valeur. Mais la dernière fois que vous avez accès t il est sûr d' std::move de sa valeur à l'autre T si vous le souhaitez. (Et 95% du temps, c'est ce que vous voulez faire)

1. si T est un type de modèle, T&& est une référence universelle au lieu de cela, dans ce cas, vous utilisez std::forward<T>(t) au lieu de std::move(t) la dernière fois. Voir cette question

33voto

Xavier Holt Points 8629

J'ai trouvé cet article 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 plus pertinente citation:

Nous avons besoin d'utiliser std::move, à partir de <utility> -- std::move est une façon de en disant: "ok, honnête à Dieu, je sais que j'ai une lvalue, mais je veux qu'il être une rvalue." std::move n'est pas, en elle-même, de déplacer quoi que ce soit; il tourne juste une lvalue dans une rvalue, de sorte que vous pouvez invoquer le déplacer constructeur.


Disons que vous avez un constructeur de déplacement 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 la copie constructeur pour initialiser this->myMember. Mais puisque c'est un constructeur de déplacement, nous savons qu' other est un objet temporaire, et donc sont donc ses membres. Donc, nous avons vraiment envie d'utiliser le plus efficace de se déplacer constructeur pour initialiser this->myMember. À l'aide de std::move permet de s'assurer que le compilateur traite other.myMember comme référence rvalue et appelle le constructeur de déplacement, comme vous pouvez vous le souhaitez:

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

Il suffit de ne pas utiliser std::move sur les objets que vous devez garder autour - des constructeurs de déplacement sont à peu près garanti à la boue de tous les objets passés en eux. C'est pourquoi ils sont utilisés uniquement avec des temporaires.

Espérons que ça aide!

5voto

Philipp Claßen Points 4863

Lorsque 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.

Que le déplacement ne doit jamais être plus cher que la copie, vous devrez presque toujours vouloir la déplacer. Et pour le déplacer, vous devez utiliser l' std::move fonction.

Quand devriez-vous éviter std::move, même si elle serait à l'abri? Je ne voudrais pas l'utiliser dans les exemples triviaux, par exemple,:

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

A côté de cela, je ne vois pas d'inconvénients. Si ce n'est pas compliquer le code, le déplacement doit être fait dès que possible à mon humble avis.

Un autre exemple, où vous ne souhaitez pas déplacer sont les valeurs de retour. La langue garantit que les valeurs de retour sont (au moins) de déménager, donc vous ne devriez pas écrire

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

(Si vous avez de la chance, la valeur de retour d'optimisation de la frappe, ce qui est encore mieux que l'opération de déplacement.)

2voto

Rahul Tripathi Points 1

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.

Checkout ce lien

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