std:: move
|
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) |
|
(C++11)
|
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) |