Namespaces
Variants

std:: move

From cppreference.net
Utilities library
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)
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)