Rvalue- och Lvalue-referenser
Svep för att visa menyn
Begreppen lvalue och rvalue används för att klassificera uttryck i två typer: de som har en stabil plats i minnet och de som är temporära.
En lvalue (vänstervärde) är ett uttryck som refererar till en specifik plats i minnet. Enkelt uttryckt är det en variabel med ett namn som kan ändras.
int x = 10;
Här är x en lvalue eftersom den har ett namn, existerar i minnet och dess värde kan ändras (x = 20).
En rvalue (högervärde) är ett temporärt värde som inte har ett eget namn och endast existerar under utvärderingen av ett uttryck.
10
x + 5
int y = x + 5;
Här är x + 5 en rvalue eftersom det bara är resultatet av en beräkning, inte lagrat som ett separat objekt, och kan inte ändras direkt.
Enkel idé:
- lvalue: något med ett namn och en minnesadress (en variabel);
- rvalue: ett temporärt resultat (ett värde eller uttryck).
Temporära värden
Ett temporärt värde är ett kortlivat, intermediärt resultat som skapas under utvärderingen av ett uttryck.
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ära värden hanteras automatiskt av kompilatorn och existerar under uttryckets eller operationens varaktighet där de skapas. Därefter kasseras de vanligtvis, och resultatet lagras i målvariabeln eller används efter behov.
Flyttsemantik
En rvalue-referens betecknas med dubbla et-tecken (&&).
Den enda skillnaden mellan en lvalue- och rvalue-referens är att rvalue kan bindas till ett temporärt objekt, medan en lvalue-referens inte kan det.
int&& ref_value = 5 * 5;
Att använda en rvalue-referens i detta sammanhang är kanske inte särskilt praktiskt, eftersom det inte finns någon fördel med att använda en rvalue-referens för ett enkelt literalvärde.
En kombination av lvalue- och rvalue-referenser används för att stödja move-semantik, vilket möjliggör överföring av resurser från ett objekt till ett annat utan onödig kopiering. Se exemplet nedan:
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` }
Men vi behöver inga kopior av a eller b. Vi ville helt enkelt byta plats på dem. Låt oss försöka igen.
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(): omvandlar en lvalue till en rvalue-referens, möjliggör flyttsemantik och överföring av ägarskap utan kopiering.
Tack för dina kommentarer!
Fråga AI
Fråga AI
Fråga vad du vill eller prova någon av de föreslagna frågorna för att starta vårt samtal