Maison >développement back-end >C++ >std::move vs std::forward : quand dois-je utiliser chacun pour un transfert parfait ?

std::move vs std::forward : quand dois-je utiliser chacun pour un transfert parfait ?

Barbara Streisand
Barbara Streisandoriginal
2024-12-15 13:24:10161parcourir

std::move vs. std::forward: When Should I Use Each for Perfect Forwarding?

std::Move vs. std::Forward : Comprendre la sémantique Rvalue

Dans la programmation C, les références rvalue et les objets temporaires jouent un rôle crucial rôle dans l’optimisation des performances du code. Deux fonctions clés, std::move et std::forward, sont utilisées pour manipuler ces entités.

std::Move

Std::move accepte un objet par valeur et le traite comme une valeur temporaire (rvalue). En règle générale, les fonctions qui prennent des références rvalue invalideront l'objet d'origine après utilisation. En utilisant std::move, vous indiquez explicitement que l'objet ne doit plus être utilisé et qu'une nouvelle valeur peut lui être attribuée.

std::Forward

Std::forward a un objectif unique : convertir un paramètre de fonction basé sur un modèle dans la même catégorie de valeur (lvalue ou rvalue) que celle prévue par l'appelant. Cela permet un « transfert parfait », permettant de transmettre les arguments rvalue en tant que rvalues ​​et les lvalues ​​en tant que lvalues.

Différences clés

  • Std::forward préserve l'objet. durée de vie, tandis que std::move implique que l'objet sera invalidé.
  • Std::forward est utilisé dans les modèles de fonction pour transmettre un paramètre à une autre fonction, en conservant sa catégorie de valeur.
  • Std::move est généralement utilisé pour indiquer que l'objet est temporaire et ne doit plus être utilisé.

Quand utiliser chaque fonction

  • Utilisez std::move lorsque vous souhaitez marquer un objet comme temporaire et autoriser il doit être invalidé.
  • Utilisez std::forward lorsque vous devez transmettre un argument d'un modèle de fonction à une autre fonction, en préservant sa catégorie de valeur.

Exemple :

Considérez ce qui suit code :

void overloaded( const int& arg ) { std::cout << "by lvalue\n"; }
void overloaded( int&& arg ) { std::cout << "by rvalue\n"; }

template<typename T>
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 );
}

Sortie :

initial caller passes rvalue:
via std::forward: by rvalue
via std::move: by rvalue
by simple passing: by rvalue
initial caller passes lvalue:
via std::forward: by lvalue
via std::move: by lvalue
by simple passing: by lvalue
  • Lors du passage d'une rvalue (5), std::forward et std::move conservent son statut de rvalue.
  • Lors du passage d'une lvalue (x), std::forward conserve son statut lvalue, tandis que std::move tente de la déplacer, l'invalidant hypothétiquement (bien que dans cet exemple, le compilateur l'optimise).

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn