Rvalue- und Lvalue-Referenzen
Swipe um das Menü anzuzeigen
Die Konzepte von lvalue und rvalue werden verwendet, um Ausdrücke in zwei Typen zu klassifizieren: solche mit einem festen Speicherort und solche, die temporär sind.
Ein lvalue (left value) ist ein Ausdruck, der sich auf einen bestimmten Speicherort bezieht. Einfach ausgedrückt ist es eine Variable mit einem Namen, die veränderbar ist.
int x = 10;
Hier ist x ein lvalue, da es einen Namen hat, im Speicher existiert und sein Wert geändert werden kann (x = 20).
Ein rvalue (right value) ist ein temporärer Wert, der keinen eigenen Namen hat und nur während der Auswertung eines Ausdrucks existiert.
10
x + 5
int y = x + 5;
Hier ist x + 5 ein rvalue, da es lediglich das Ergebnis einer Berechnung ist, nicht als separates Objekt gespeichert wird und nicht direkt verändert werden kann.
Einfache Idee:
- lvalue: etwas mit Namen und Speicheradresse (eine Variable);
- rvalue: ein temporäres Ergebnis (ein Wert oder Ausdruck).
Temporäre Werte
Ein temporärer Wert ist ein kurzlebiges, intermediäres Ergebnis, das während der Auswertung eines Ausdrucks erzeugt wird.
rvalue.h
12345678// `(27 + 6 + 3 + 2)` is a tempopary value int sum = 27 + 6 + 3 + 2; // `static_cast<float>(sum)` is a tempopary value float avarage = static_cast<float>(sum) / count; // std::max(7, 9) will return a tempopary value int largest = std::max(7, 9);
Temporäre Werte werden automatisch vom Compiler verwaltet und existieren für die Dauer des Ausdrucks oder der Operation, in der sie erstellt werden. Danach werden sie in der Regel verworfen, und das Ergebnis wird in der Zielvariablen gespeichert oder nach Bedarf verwendet.
Move Semantik
Ein Rvalue-Referenz wird durch das doppelte kaufmännische Und (&&) dargestellt.
Der einzige Unterschied zwischen einer Lvalue- und einer Rvalue-Referenz besteht darin, dass eine Rvalue-Referenz an ein temporäres Objekt gebunden werden kann, während eine Lvalue-Referenz dies nicht kann.
int&& ref_value = 5 * 5;
Die Verwendung einer Rvalue-Referenz in diesem Zusammenhang ist möglicherweise nicht sehr praktisch, da es keinen Vorteil bietet, eine Rvalue-Referenz für ein einfaches Literal zu verwenden.
Eine Kombination aus lvalue- und rvalue-Referenzen wird verwendet, um Move-Semantik zu unterstützen. Dadurch können Ressourcen von einem Objekt auf ein anderes übertragen werden, ohne unnötiges Kopieren. Siehe das folgende Beispiel:
swap.h
123456std::string swap(std::string& a, std::string& b) { std::string tmp(a); // We have two copies of string `a` a = b; // Now we have two copies of string `b` b = tmp; // And now we have two copies of string `tmp` }
Aber wir benötigen keine Kopien von a oder b. Wir wollten sie einfach nur tauschen. Versuchen wir es erneut.
main.cpp
1234567891011121314151617181920212223#include <iostream> void swap(std::string &a, std::string &b) { // Move the content of a into temp std::string temp(std::move(a)); // Move the content of b into a a = std::move(b); // Move the content of temp into b b = std::move(temp); } int main() { std::string a = "Hello\n"; std::string b = "Bye\n"; swap(a, b); std::cout << a << b; }
std::move(): wandelt ein Lvalue in eine Rvalue-Referenz um, ermöglicht Move-Semantik und die Übertragung des Besitzes ohne Kopieren.
Danke für Ihr Feedback!
Fragen Sie AI
Fragen Sie AI
Fragen Sie alles oder probieren Sie eine der vorgeschlagenen Fragen, um unser Gespräch zu beginnen