Namespaces
Variants

std:: move

From cppreference.net
Utilities library
Défini dans l'en-tête <utility>
template < class T >
typename std:: remove_reference < T > :: type && move ( T && t ) noexcept ;
(depuis C++11)
(jusqu'à C++14)
template < class T >
constexpr std:: remove_reference_t < T > && move ( T && t ) noexcept ;
(depuis C++14)

std::move est utilisé pour indiquer qu'un objet t peut être "déplacé", permettant ainsi le transfert efficace des ressources de t vers un autre objet.

En particulier, std::move produit une expression xvalue qui identifie son argument t . Elle est exactement équivalente à un static_cast vers un type de référence rvalue.

Table des matières

Paramètres

t - l'objet à déplacer

Valeur de retour

static_cast < typename std:: remove_reference < T > :: type && > ( t )

Notes

Les fonctions qui acceptent des paramètres de référence à valeur de déplacement (y compris les constructeurs de déplacement , opérateurs d'affectation par déplacement , et les fonctions membres régulières telles que std::vector::push_back ) sont sélectionnées, par résolution de surcharge , lorsqu'elles sont appelées avec des arguments de valeur de déplacement (soit des prvalues comme un objet temporaire ou des xvalues comme ceux produits par std::move ). Si l'argument identifie un objet propriétaire de ressources, ces surcharges ont la possibilité, mais pas l'obligation, de déplacer toutes les ressources détenues par l'argument. Par exemple, un constructeur de déplacement d'une liste chaînée pourrait copier le pointeur vers la tête de la liste et stocker nullptr dans l'argument au lieu d'allouer et copier les nœuds individuellement.

Les noms des variables de rvalue reference sont des lvalues et doivent être convertis en xvalues pour être liés aux surcharges de fonctions qui acceptent des paramètres de rvalue reference, ce qui explique pourquoi les move constructors et les move assignment operators utilisent généralement std::move :

// Constructeur de déplacement simple
A(A&& arg) : member(std::move(arg.member)) // l'expression "arg.member" est une lvalue
{}
// Opérateur d'affectation de déplacement simple
A& operator=(A&& other)
{
    member = std::move(other.member);
    return *this;
}

Une exception est lorsque le type du paramètre de fonction est une référence de transfert (qui ressemble à une référence rvalue vers un paramètre de type template), auquel cas std::forward est utilisé à la place.

Sauf indication contraire, tous les objets de la bibliothèque standard qui ont été déplacés sont placés dans un "état valide mais non spécifié", ce qui signifie que les invariants de classe de l'objet sont maintenus (ainsi, les fonctions sans préconditions, telles que l'opérateur d'affectation, peuvent être utilisées en toute sécurité sur l'objet après son déplacement) :

std::vector<std::string> v;
std::string str = "example";
v.push_back(std::move(str)); // str est maintenant valide mais non spécifiée
str.back(); // comportement indéfini si size() == 0 : back() a une précondition !empty()
if (!str.empty())
    str.back(); // OK, empty() n'a pas de précondition et la précondition de back() est satisfaite
str.clear(); // OK, clear() n'a pas de préconditions

De plus, les fonctions de la bibliothèque standard appelées avec des arguments xvalue peuvent supposer que l'argument est la seule référence à l'objet ; s'il a été construit à partir d'un lvalue avec std::move , aucune vérification d'aliasing n'est effectuée. Cependant, l'auto-affectation par déplacement des types de la bibliothèque standard garantit que l'objet sera placé dans un état valide (mais généralement non spécifié) :

std::vector<int> v = {2, 3, 3};
v = std::move(v); // la valeur de v n'est pas spécifiée

Exemple

#include <iomanip>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
int main()
{
    std::string str = "Salut";
    std::vector<std::string> v;
    // utilise la surcharge push_back(const T&), ce qui signifie
    // que nous subirons le coût de la copie de str
    v.push_back(str);
    std::cout << "Après copie, str est " << std::quoted(str) << '\n';
    // utilise la surcharge push_back(T&&) par référence rvalue,
    // ce qui signifie qu'aucune chaîne ne sera copiée ; au lieu de cela, le contenu
    // de str sera déplacé dans le vecteur. C'est moins
    // coûteux, mais signifie aussi que str pourrait maintenant être vide.
    v.push_back(std::move(str));
    std::cout << "Après déplacement, str est " << std::quoted(str) << '\n';
    std::cout << "Le contenu du vecteur est {" << std::quoted(v[0])
              << ", " << std::quoted(v[1]) << "}\n";
}

Sortie possible :

After copy, str is "Salut"
After move, str is ""
The contents of the vector are {"Salut", "Salut"}

Voir aussi

(C++11)
transmet un argument de fonction et utilise l'argument de type template pour préserver sa catégorie de valeur
(modèle de fonction)
convertit l'argument en xvalue si le constructeur de déplacement ne lève pas d'exception
(modèle de fonction)
(C++11)
déplace une plage d'éléments vers un nouvel emplacement
(modèle de fonction)