std:: move
|
Definiert im Header
<utility>
|
||
|
template
<
class
T
>
typename std:: remove_reference < T > :: type && move ( T && t ) noexcept ; |
(seit C++11)
(bis C++14) |
|
|
template
<
class
T
>
constexpr std:: remove_reference_t < T > && move ( T && t ) noexcept ; |
(seit C++14) | |
std::move
wird verwendet, um
anzuzeigen
, dass ein Objekt
t
"verschoben werden kann", d.h. die effiziente Übertragung von Ressourcen von
t
zu einem anderen Objekt ermöglicht wird.
Insbesondere erzeugt
std::move
einen
xvalue-Ausdruck
, der sein Argument
t
identifiziert. Es ist exakt äquivalent zu einem
static_cast
auf einen Rvalue-Referenztyp.
Inhaltsverzeichnis |
Parameter
| t | - | das zu verschiebende Objekt |
Rückgabewert
static_cast < typename std:: remove_reference < T > :: type && > ( t )
Hinweise
Die Funktionen, die Rvalue-Referenzparameter akzeptieren (einschließlich
Move-Konstruktoren
,
Move-Zuweisungsoperatoren
und reguläre Memberfunktionen wie
std::vector::push_back
) werden durch
Überladungsauflösung
ausgewählt, wenn sie mit
Rvalue
-Argumenten aufgerufen werden (entweder
Prvalues
wie ein temporäres Objekt oder
Xvalues
wie diejenigen, die durch
std::move
erzeugt werden). Wenn das Argument ein ressourcenbesitzendes Objekt identifiziert, haben diese Überladungen die Möglichkeit, aber nicht die Verpflichtung, alle vom Argument gehaltenen Ressourcen zu
verschieben
. Beispielsweise könnte ein Move-Konstruktor einer verketteten Liste den Zeiger auf den Listenkopf kopieren und
nullptr
im Argument speichern, anstatt einzelne Knoten zu allokieren und zu kopieren.
Namen von
rvalue reference
-Variablen sind
lvalues
und müssen zu
xvalues
konvertiert werden, um an die Funktionsüberladungen gebunden zu werden, die rvalue reference-Parameter akzeptieren. Deshalb verwenden
move constructors
und
move assignment operators
typischerweise
std::move
:
// Einfacher Move-Konstruktor A(A&& arg) : member(std::move(arg.member)) // der Ausdruck "arg.member" ist ein Lvalue {} // Einfacher Move-Zuweisungsoperator A& operator=(A&& other) { member = std::move(other.member); return *this; }
Eine Ausnahme liegt vor, wenn der Typ des Funktionsparameters eine Forwarding-Referenz (die wie eine Rvalue-Referenz auf einen Typ-Template-Parameter aussieht) ist, in welchem Fall std::forward stattdessen verwendet wird.
Sofern nicht anders angegeben, befinden sich alle Standardbibliothek-Objekte, von denen verschoben wurde, in einem "gültigen, aber nicht spezifizierten Zustand". Dies bedeutet, dass die Klasseninvarianten des Objekts erhalten bleiben (sodass Funktionen ohne Vorbedingungen, wie der Zuweisungsoperator, sicher auf das Objekt angewendet werden können, nachdem von ihm verschoben wurde):
std::vector<std::string> v; std::string str = "example"; v.push_back(std::move(str)); // str ist nun gültig aber unspezifiziert str.back(); // undefiniertes Verhalten wenn size() == 0: back() hat eine Vorbedingung !empty() if (!str.empty()) str.back(); // OK, empty() hat keine Vorbedingung und back() Vorbedingung ist erfüllt str.clear(); // OK, clear() hat keine Vorbedingungen
Außerdem können Standardbibliotheksfunktionen, die mit xvalue-Argumenten aufgerufen werden, davon ausgehen, dass das Argument die einzige Referenz auf das Objekt ist; wenn es von einem lvalue mit
std::move
konstruiert wurde, werden keine Aliasing-Prüfungen durchgeführt. Allerdings ist Selbst-Zuweisung mit Verschiebung bei Standardbibliothekstypen garantiert, das Objekt in einen gültigen (aber üblicherweise nicht spezifizierten) Zustand zu versetzen:
std::vector<int> v = {2, 3, 3}; v = std::move(v); // der Wert von v ist nicht spezifiziert
Beispiel
#include <iomanip> #include <iostream> #include <string> #include <utility> #include <vector> int main() { std::string str = "Salut"; std::vector<std::string> v; // verwendet die push_back(const T&)-Überladung, was bedeutet, // dass wir die Kosten für das Kopieren von str tragen v.push_back(str); std::cout << "After copy, str is " << std::quoted(str) << '\n'; // verwendet die push_back(T&&)-Überladung mit Rvalue-Referenz, // was bedeutet, dass keine Zeichenketten kopiert werden; stattdessen werden die Inhalte // von str in den Vektor verschoben. Dies ist weniger // aufwändig, bedeutet aber auch, dass str nun leer sein könnte. v.push_back(std::move(str)); std::cout << "After move, str is " << std::quoted(str) << '\n'; std::cout << "The contents of the vector are {" << std::quoted(v[0]) << ", " << std::quoted(v[1]) << "}\n"; }
Mögliche Ausgabe:
After copy, str is "Salut"
After move, str is ""
The contents of the vector are {"Salut", "Salut"}
Siehe auch
|
(C++11)
|
leitet ein Funktionsargument weiter und verwendet den Typ-Template-Parameter, um seine Wertkategorie zu erhalten
(Funktions-Template) |
|
(C++11)
|
konvertiert das Argument in einen xvalue, wenn der Move-Konstruktor keine Ausnahme wirft
(Funktions-Template) |
|
(C++11)
|
verschiebt einen Bereich von Elementen an einen neuen Speicherort
(Funktions-Template) |