Heim >Backend-Entwicklung >C++ >Wie bindet std::move() an L-Werte, wenn R-Wert-Referenzen nur an R-Werte binden sollen?

Wie bindet std::move() an L-Werte, wenn R-Wert-Referenzen nur an R-Werte binden sollen?

DDD
DDDOriginal
2024-11-14 10:46:011035Durchsuche

How does std::move() bind to lvalues when rvalue references are supposed to only bind to rvalues?

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn