C++
VeröffentlichtRevision 1

Verschieben, std::move und Wertkategorien

Kopieren erzeugt einen weiteren Wert mit passendem eigenen Zustand. Verschieben, englisch move, kann Ressourcen eines nicht mehr benötigten Objekts übernehmen. Ein Vector kann so häufig seinen internen Speicher weiterreichen, statt alle Elemente einzeln zu kopieren.

Verschieben, std::move und Wertkategorien#

Modernes C++ · Lektion 45 von 60

Voraussetzungen: Smart Pointer, Konstruktoren. Lernziel: Du erkennst den Unterschied zwischen Kopieren und Ressourcenübernahme.

Kopieren erzeugt einen weiteren Wert mit passendem eigenen Zustand. Verschieben, englisch move, kann Ressourcen eines nicht mehr benötigten Objekts übernehmen. Ein Vector kann so häufig seinen internen Speicher weiterreichen, statt alle Elemente einzeln zu kopieren.

C++
1#include <iostream>2#include <string>3#include <utility>4 5int main() {6    std::string quelle{"Ein laengerer Beispieltext"};7    std::string ziel = std::move(quelle);8    std::cout << ziel << '\n';9    quelle = "Neuer Inhalt";10    std::cout << quelle << '\n';11}

std::move verschiebt selbst noch keine Bytes. Es wandelt die Ausdruckskategorie so um, dass eine passende Move-Operation gewählt werden kann. Ob anschließend tatsächlich eine Verschiebung oder eine Kopie stattfindet, hängt vom Zieltyp und dessen Funktionen ab.

Lvalue, Rvalue und &&#

Eine Wertkategorie beschreibt die Rolle eines Ausdrucks, zusätzlich zu seinem Typ. Ein Lvalue bezeichnet typischerweise ein identifizierbares Objekt, etwa eine benannte Variable. Rvalue umfasst Kategorien für temporäre oder zur Ressourcenübernahme geeignete Werte. std::move(quelle) macht den Ausdruck zu einem Xvalue, einer solchen zur Übernahme geeigneten Kategorie.

T&& ist in einer gewöhnlichen entsprechenden Deklaration eine Rvalue-Referenz. In bestimmten abgeleiteten Templatekontexten wird daraus eine Forwarding-Referenz, die verschiedene Kategorien erhalten kann. Für erste Anwendungen brauchst du keine eigenen komplizierten Weiterleitungsfunktionen.

Zustand nach dem Move#

Ein verschobener Standard-String bleibt grundsätzlich gültig, sein genauer Inhalt ist aber nicht allgemein zugesichert. Verlasse dich nicht darauf, dass er immer leer ist. Du kannst ihn zerstören oder wie im Beispiel neu zuweisen. Beachte bei anderen Operationen weiterhin deren Vorbedingungen.

Für unique_ptr gilt die stärkere konkrete Zusage, dass der abgegebene Besitzer leer wird. Lies deshalb die Regeln des jeweiligen Typs, statt einen Sonderfall auf alle Typen zu übertragen.

Rückgaben nicht vorschnell „optimieren“#

C++ kann bei geeigneten Wertrückgaben Kopien oder Verschiebungen ganz vermeiden. Das heißt Copy Elision. Schreibe eine lokale Rückgabe normalerweise als return ergebnis;. Ein zusätzliches std::move kann bestimmte Optimierungsmöglichkeiten gerade verhindern.

Übung#

Warum ist eine Ausgabe des ursprünglichen Stringinhalts nach std::move kein verlässlicher Test?

Lösung

Der genaue Inhalt des verschobenen Strings ist nicht allgemein festgelegt. Prüfe das Ziel und verwende die Quelle nur gemäß ihrem gültigen Zustand und den jeweiligen Vorbedingungen weiter.

Weiterlernen#

Zurück: Lambdas und bewusstes Einfangen von Werten · Kursübersicht · Weiter: Fehlende Werte und Alternativen: optional und variant

Mitwirkende 1

Menschen, deren Änderungen in dieser Seite veröffentlicht wurden.

Kommentare 0

Kommentare sind für diese Seite deaktiviert.