Das Geheimnis der Konvertierungsmagie von std::move lüften
Beim Aufruf von std::move() ist es rätselhaft zu beobachten, dass die referenzierte Der R-Wert-Parameter kann an L-Werte gebunden werden, die normalerweise nicht an R-Wert-Referenzen angehängt werden dürfen. Wenn man sich mit der Implementierung von std::move() befasst, offenbart sich der Schlüssel zu diesem scheinbaren Paradoxon.
Analyse der std::move()-Implementierung
Beginnend mit dem Verfeinerten Version von std::move():
template <typename T> typename remove_reference<T>::type&& move(T&& arg) { return static_cast<typename remove_reference<T>::type&&>(arg); }
Fall 1: Aufruf von move() mit R-Werten
Wenn move() mit R-Werten verwendet wird, z ein temporäres Objekt:
Object a = std::move(Object()); // Object() is temporary, hence prvalue
Die resultierende Vorlageninstanziierung ist:
remove_reference<Object>::type&& move(Object&& arg) { return static_cast<remove_reference<Object>::type&&>(arg); }
Da „remove_reference“ T& in T oder T&& in T umwandelt und Object ein einfacher Wert ist, ist die endgültige Funktionsmorphologie wird zu:
Object&& move(Object&& arg) { return static_cast<Object&&>(arg); }
Die Besetzung ist entscheidend, da benannte R-Wert-Referenzen als L-Werte behandelt werden.
Fall 2: Aufruf von move() mit L-Werten
Wenn move() mit L-Werten aufgerufen wird:
Object a; // a is an lvalue Object b = std::move(a);
Die resultierende move()-Instanziierung lautet:
remove_reference<Object&>::type&& move(Object& && arg) { return static_cast<remove_reference<Object&>::type&&>(arg); }
Auch hier übersetzt „remove_reference“ Object& in Object und ergibt:
Object&& move(Object& && arg) { return static_cast<Object&&>(arg); }
Die Essenz des Referenzkollaps
Das Verständnis von Objekt& && und seiner Fähigkeit, sich an L-Werte zu binden, ist der Schlüssel zur Lösung des Rätsels. C 11 führt spezielle Regeln für das Reduzieren von Referenzen ein, die Folgendes vorschreiben:
Object & && = Object & Object & &&& = Object & Object && & = Object & Object && &&& = Object &&
Somit wird Object& && tatsächlich in Object& übersetzt, eine typische L-Wert-Referenz, die sich mühelos an L-Werte bindet.
Die Resultierende Funktion
Mit diesen Regeln wird die endgültige Funktion zu:
Object&& move(Object& arg) { return static_cast<Object&&>(arg); }
Sie spiegelt die Instanziierung für R-Werte wider und wandelt ihr Argument in eine R-Wert-Referenz um, wodurch ein einheitliches Verhalten sichergestellt wird .
Die Bedeutung von „remove_reference“
Der Zweck von „remove_reference“ wird deutlich, wenn man eine alternative Funktion untersucht:
template <typename T> T&& wanna_be_move(T&& arg) { return static_cast<T&&>(arg); }
Bei Instanziierung mit einem L-Wert:
Object& && wanna_be_move(Object& && arg) { return static_cast<Object& &&&>(arg); }
Das Anwenden von Regeln zum Reduzieren von Referenzen zeigt eine unbrauchbare verschiebungsähnliche Funktion, die L-Werte für L-Wert-Argumente zurückgibt. Der Übeltäter ist das Fehlen von „remove_reference“, was die ordnungsgemäße Konvertierung in R-Wert-Referenzen behindert.
Das obige ist der detaillierte Inhalt vonWie bindet std::move() an L-Werte, wenn R-Wert-Referenzen nur an R-Werte binden sollen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!