std::move et std::forward
Convertir des lvalues en rvalues avec std::move et préserver la catégorie de valeur avec std::forward
std::move et std::forward est une leçon C++ Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage C++ Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours C++ Academy comprend 4 leçons au total.
Deux cousines, des rôles différents
std::move et std::forward sont toutes deux des conversions effectuées à la compilation. Elles se ressemblent, mais résolvent des problèmes différents.
std::move : toujours convertir en rvalue
std::move(x) convertit systématiquement x en référence rvalue. La fonction qui la reçoit peut alors récupérer ses ressources.
std::string s = "Hello";
std::string t = std::move(s); // move-constructs t from s
// s is now in a valid-but-unspecified stateQuand utiliser move
Utilisez std::move dans les cas suivants :
- Les constructeurs de déplacement et les opérateurs d’affectation par déplacement
- Le retour d’une variable locale lorsque vous voulez forcer un déplacement (rarement nécessaire, car la RVO s’applique généralement)
- La transmission à une fonction réceptrice d’une variable locale dont vous n’avez plus besoin
Implémentation de std::move
Il s’agit simplement d’un static_cast déguisé :
template <typename T>
typename std::remove_reference<T>::type&& move(T&& t) noexcept {
return static_cast<typename std::remove_reference<T>::type&&>(t);
}std::forward : préserver la catégorie
Dans un modèle qui utilise une référence de transfert (T&&), std::forward<T>(x) reconvertit x dans sa catégorie d’origine (lvalue ou rvalue). Il est utilisé pour le transfert parfait.
template <typename T>
void wrapper(T&& arg) {
target(std::forward<T>(arg)); // forwards as lvalue or rvalue depending on T
}Pourquoi le transfert est nécessaire
Dans le modèle, le paramètre possède un nom, ce qui en fait une lvalue, même si l’appelant a transmis une rvalue. std::forward retrouve la catégorie d’origine.
Sans std::forward
Sans forward, chaque argument serait transmis comme une lvalue à l’intérieur du wrapper, ce qui annulerait toute sémantique de déplacement souhaitée par l’appelant.
template <typename T>
void wrapper(T&& arg) {
target(arg); // always lvalue — wrong
}Toujours spécifier le paramètre de modèle de forward
std::forward<T> exige l’argument explicite du modèle. Sans lui, le comportement serait incorrect.
Exemple de transfert parfait
Une fonction de fabrique qui transmet les arguments du constructeur préserve les distinctions entre rvalues et lvalues pour gagner en efficacité.
template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}Déplacer une seule fois
Chaque objet ne devrait être déplacé qu’une seule fois au maximum. Après le déplacement, il se trouve dans un état valide mais non spécifié ; en général, vous le réaffectez ou vous le détruisez. Utiliser un objet dont les ressources ont été déplacées sans le réaffecter auparavant risque de provoquer des erreurs subtiles.
Règles générales
Modèle mental rapide :
- Vous avez un type concret et voulez le déplacer →
std::move - Vous avez un paramètre de modèle et voulez préserver sa catégorie →
std::forward<T>
Vérification rapide
Dans une fonction modèle dont le paramètre est T&& arg, comment transmettre arg en préservant sa catégorie lvalue/rvalue ?
Récapitulatif
std::move convertit systématiquement en rvalue : utilisez-le sur des objets concrets dont vous voulez récupérer les ressources. std::forward<T> préserve la catégorie de valeur dans les modèles génériques : utilisez-le pour le transfert parfait.
Questions Fréquemment Posées
La leçon « std::move et std::forward » est-elle gratuite ?
Oui — le texte complet de « std::move et std::forward » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours C++ Academy, passe à CoddyKit PRO. Le cours C++ Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « std::move et std::forward » ?
Convertir des lvalues en rvalues avec std::move et préserver la catégorie de valeur avec std::forward Tu pratiques C++ Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer C++ Academy ?
Aucune expérience préalable n'est requise. C++ Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.
Combien de temps prend la leçon « std::move et std::forward » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon C++ Academy ?
Oui. Chaque leçon C++ Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Lvalue ou rvalue : la distinction
- Références rvalue et syntaxe &&
- std::move et std::forward
- Constructeurs de déplacement et affectation par déplacement