左值 & 右值
在講 std::move 之前,我們先來了解左值右值,不然根本不知道 std::move 在幹嘛。 在 C++ 中,左值(lvalue)和右值(rvalue)是兩個基本的值類型概念,它們對變量、表達式以及操作的語法和語義有著重要影響。
一句話講明: = 左邊的就是左值, = 右邊的就是右值
左值
左值(lvalue,指 “locator value”)是指那些表示某個內存位置的值。左值是可以出現在賦值運算符左側的值,這意味著它們可以被賦予新的值。左值通常是具名變量或可取地址的表達式。
特性:
- 可以取地址(使用
&操作符)。 - 可以被賦值。
- 在內存中有持久的存儲位置。
看 code 吧, 這次註解的地方是重點
1
2
3
4
5
int x = 10; // x 是左值,可以取地址 &x 並且可以賦值 x = 20;
int* ptr = &x; // ptr 是左值,可以取地址 &ptr 並且可以賦值 ptr = &y;
x = 5; // x 是左值,可以被賦值新值
右值
右值(rvalue,指 “right value”)是那些不表示特定內存位置的值。右值通常是臨時對象、常量或表達式的結果,這些值不能取地址,也不能被賦值。
特性:
- 不能取地址。
- 通常是臨時對象,在表達式求值後即被銷毀。
- 不能被賦值。
註解的地方是重點
1
2
3
4
int y = 10; // 10 是右值,是一個常量
int z = x + 5; // (x + 5) 是右值,是表達式的結果
int* p = &x; // p 是左值,而 &x 是右值(地址常量)
左值引用(lvalue reference)
這個沒什麼特別的,寫過 c++ 的一定用過(大概吧) 左值引用綁定到左值,可以通過 & 符號來聲明。
1
2
3
int x = 10;
int& ref = x; // ref 是左值引用,綁定到左值 x
右值引用(rvalue reference)
這個就有趣了,這是 C++11 引入的一個重要特性。 右值引用綁定到右值,可以通過 && 符號來聲明。右值引用引入了 std::move 移動語義和完美轉發。
1
2
3
4
5
int&& rref = 20; // rref 是右值引用,綁定到右值 20
int x = 10;
int&& rref2 = x + 5; // rref2 是右值引用,綁定到表達式結果 (x + 5)
直接比較的執行結果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <utility> // std::move
void printValue(const int& lref) {
std::cout << "Lvalue reference: " << lref << std::endl;
}
void printValue(const int&& rref) {
std::cout << "Rvalue reference: " << rref << std::endl;
}
int main()
{
int x = 10; // x 是左值
printValue(x); // 傳遞左值引用
printValue(20); // 傳遞右值引用
printValue(std::move(x)); // 將左值 x 轉換為右值引用
auto temp = std::move(x);
printValue(temp); // temp 仍為左值
return 0;
}
結果:
在這個例子中,函數 printValue 有兩個重載版本,一個接受左值引用,另一個接受右值引用。根據傳遞的參數是左值還是右值,對應的函數會被調用。 std::move 只是將左值暫時變成右值,因此上述 temp 還是左值。
還看不出 std::move 的使用時機吧,放心,下一篇會詳細介紹。

