Quelle est la différence entre std::move et std::forward
j'ai vu ça ici: Constructeur de Déplacement d'appel de la classe de base Constructeur de Déplacement
pourrait quelqu'un expliquer:
- la différence entre
std::move
etstd::forward
, de préférence avec quelques exemples de code? - Comment penser facilement, et quand utiliser les
3 réponses
std::move
prend un objet et vous permet de le traiter comme une valeur temporaire. Bien que ce ne soit pas une exigence sémantique, typiquement une fonction acceptant une référence à une valeur de R l'invalidera. Quand vous voyez std::move
, cela indique que la valeur de l'objet ne doit pas être utilisée après, mais vous pouvez toujours assigner une nouvelle valeur et continuer à l'utiliser.
std::forward
a un cas d'utilisation unique: pour lancer un paramètre de fonction templated (à l'intérieur du fonction) à la catégorie de valeur (lvalue ou rvalue) que l'appelant utilisait pour la passer. Cela permet rvalue les arguments passés sur que rvalues, et lvalues être transmis que lvalues, un système appelé "transfert parfait."
à illustrent :
void overloaded( int const &arg ) { std::cout << "by lvalue\n"; }
void overloaded( int && arg ) { std::cout << "by rvalue\n"; }
template< typename t >
/* "t &&" with "t" being template param is special, and adjusts "t" to be
(for example) "int &" or non-ref "int" so std::forward knows what to do. */
void forwarding( t && arg ) {
std::cout << "via std::forward: ";
overloaded( std::forward< t >( arg ) );
std::cout << "via std::move: ";
overloaded( std::move( arg ) ); // conceptually this would invalidate arg
std::cout << "by simple passing: ";
overloaded( arg );
}
int main() {
std::cout << "initial caller passes rvalue:\n";
forwarding( 5 );
std::cout << "initial caller passes lvalue:\n";
int x = 5;
forwarding( x );
}
comme le mentionne Howard, il y a aussi des similitudes car ces deux fonctions sont simplement moulées en type de référence. Mais en dehors de ces cas d'utilisation spécifiques (qui couvrent 99,9% des utilité des moulages de référence rvalue), vous devriez utiliser static_cast
directement et écrire une bonne explication de ce que vous faites.
les deux std::forward
et std::move
ne sont que des moulages.
X x;
std::move(x);
l'expression de la valeur l x
de type X est remplacée par une expression de la valeur R de type X (une valeur X pour être exacte). move
peut également accepter une valeur R:
std::move(make_X());
et dans ce cas c'est une fonction d'identité: prend une valeur de type X et renvoie une valeur de type X.
avec std::forward
vous pouvez sélectionner le destination dans une certaine mesure:
X x;
std::forward<Y>(x);
renvoie l'expression de valeur x
de type X à une expression de type Y. Il y a des contraintes sur ce que peut être Y.
Y peut être accessible de Base de X, ou une référence à une Base de X. Y X, ou une référence à X. On ne peut pas jeté cv-qualifications avec forward
, mais on peut ajouter cv-qualificatifs. Y ne peut pas être un type qui est simplement convertible à partir de X, sauf via une Base accessible conversion.
si Y est une référence de lvalue, le résultat sera une expression de lvalue. Si Y n'est pas une référence de lvalue, le résultat sera une expression de rvalue (xvalue pour être précis).
forward
ne peut prendre un argument rvalue que si Y n'est pas une référence lvalue. C'est-à-dire que vous ne pouvez pas attribuer une valeur à lvalue. Pour des raisons de sécurité, cela conduit souvent à des références pendantes. Mais le casting d'une rvalue à rvalue est ok et autorisé.
Si vous essayez de spécifier Y à quelque chose qui n'est pas autorisé, l'erreur sera pris au moment de la compilation, pas de temps d'exécution.
std::forward
est utilisé pour forward paramètre exactement comme il a été passé à une fonction. Comme montré ici:
Lors de l'utilisation de std::avant d'avancer des arguments?
L'utilisation de std::move
offre un objet comme une valeur R, pour éventuellement correspondre à un constructeur de mouvements ou à une fonction acceptant des valeurs R. Il le fait pour std::move(x)
même si x
n'est pas une valeur en soi.