文章目錄
- 概述
- 左值
- 右值
- 右值引用
- 左值和右值的互換
- 小結
概述
左值和右值屬于2中不同的表達式類型;它們在表達式中扮演不同的角色,特別是在賦值操作和函數參數傳遞中。
左值
定義:左值是指那些在內存中有確定位置的表達式,可以出現在賦值表達式的左側,即可以被賦值。
特征:
左值可以出現在賦值操作的左側,也可以出現在函數的參數中(如果函數參數是引用類型)。
關鍵點:表達式左邊,可以被賦值可以推導出來;函數參數+參數是引用類型
右值
==定義:右值是指那些沒有存儲在內存中,或者沒有持久存儲位置的表達式。==它們通常表示臨時值或字面量。
特征:右值通常不能出現在賦值操作的左側,但C++11引入了右值引用(rvalue reference),允許右值出現在賦值操作的左側,并且可以用于實現移動語義(move semantics)。
關鍵點:右值一般在表達式右邊。
右值引用
定義:C++11引入了右值引用,用雙寫的&&表示,它允許程序員更有效地處理右值。
用途:
- 移動語義:允許臨時對象的資源被“移動”到另一個對象中,而不是進行復制。一般用std::move來實現
- 完美轉發:在模板編程中,可以轉發參數的值類別(左值或右值)。 這個一般用std::forward來實現
示例1(移動語義):
#include <iostream>
#include <vector>class ResourceHolder {
public:ResourceHolder(int size) : data(new int[size]) {std::cout << "ResourceHolder created with size " << size << std::endl;}~ResourceHolder() {std::cout << "ResourceHolder destroyed" << std::endl;delete[] data;}// Move constructorResourceHolder(ResourceHolder&& other) {data = other.data;other.data = nullptr;}// Copy constructor (deleted)ResourceHolder(const ResourceHolder&) = delete;// Move assignment operatorResourceHolder& operator=(ResourceHolder&& other) {if (this != &other) {delete[] data;data = other.data;other.data = nullptr;}return *this;}// Copy assignment operator (deleted)ResourceHolder& operator=(const ResourceHolder&) = delete;private:int* data;
};int main() {ResourceHolder largeResource(1024);std::vector<ResourceHolder> resources;// 使用 std::move 將 largeResource 移動到 vector 中resources.push_back(std::move(largeResource));// largeResource 現在是一個空的 ResourceHolder 對象return 0;
}
示例1(完美轉發):
#include <utility>
#include <iostream>// 假設這是我們要轉發參數的目標函數
void process(int& i) {std::cout << "process(int&) called with " << i << std::endl;
}void process(int&& i) {std::cout << "process(int&&) called with " << i << std::endl;
}// 模板函數,使用 std::forward 來轉發參數
template<typename T>
void wrapper(T&& arg) {process(std::forward<T>(arg));
}int main() {int a = 5;wrapper(a); // a 是左值,調用 process(int& i)wrapper(10); // 10 是右值,調用 process(int&& i)
}
左值和右值的互換
常量左值:通過const關鍵字可以創建一個常量左值,它不能被賦值。
右值轉換為左值:通過賦值操作,右值可以轉換為左值。例如,int &&a = 10; 這里的10是一個右值,但通過賦值操作,a成為了一個左值引用。
小結
本篇主要寫了一個新的概念,右值引用;左值右值是一直存在的,只不過引入了一個右值引用,然后多了一個左值轉成右值(一般用std::move),還多了一個完美轉發(一般用std::forward)。例子僅供參考,理解概念使用。還是先把概念搞明白,然后才好理解;感興趣可以一起學習學習。概念這東西,很多人都不喜歡,卻都逃不掉,多看幾遍就好了。OK,翻篇。