網站首頁 編程語言 正文
1、右值
1.1 簡介
首先區分一下左右值:
- 左值是指存儲在內存中、有明確存儲地址(可取地址)的數據;
- 右值是指可以提供數據值的數據(不可取地址)
如int a=123;123是右值, a是左值。總的來說 可以對表達式取地址(&)就是左值,否則為右值
而C++11 中右值又可以分為兩種:
- 純右值:非引用返回的臨時變量、運算表達式產生的臨時變量如a+b、原始字面量和 lambda 表達式等
- 將亡值:與右值引用相關的表達式、返回T&& 類型函數的返回值
1.2 右值引用
常見的 & 為左值引用、右值引用使用 && 表示
int&& a = 123;
int &b = a;
int &&c = a;//不合法
如上 a 是對123的右值引用,但是a本身是左值,其在內存中有明確的存儲地址,所以c不能再對其進行左值引用。
1.3 右值引用的意義
可以將資源(堆、系統對象等)通過淺拷貝從一個對象轉移到另一個對象這樣就能減少不必要的臨時對象的創建、拷貝以及銷毀,可以大幅提高應用程序的性能。
#include <iostream>
using namespace std;
class Test
{
public:
Test() : num(new int(100))
{
cout << "construct" << endl;
}
Test(const Test& a) : num(new int(*a.num))
{
cout << "copy construct" << endl;
}
// 移動構造函數其實就是將入參的資源賦值給自己,并將入參的對應資源指針制空,
Test(Test&& a) : num(a.num)
{
cout << "rv copy construct" << endl;
a.num = nullptr;
}
~Test()
{
delete num;
}
int* num;
};
Test getObj()
{
Test t;
return t;
}
int main()
{
Test t = getObj();
return 0;
};
getObj()會得到一個非引用的臨時對象,是純右值,如果只有拷貝構造函數就只能再次new一塊區域去保存該右值的資源,這是因為不能確定拷貝構造傳入的參數后面是不是還會繼續被使用, 只好進行深拷貝。而對于傳入右值的情況,可以確定右值以后不會再進行訪問,因此可直接將其指針復給新對象,將入參的對應指針置為null,防止析構造成野指針,避免深拷貝帶來的性能消耗。
由此可見,右值引用具有移動語義:將確定后續不再使用的對象中的資源轉移給新的對象,雖然左值引用也能夠做到資源轉移,但傳入的左值后續可能還會被更改和使用,個人認為右值引用恰好做到了這種區分。
2、move
使用std::move方法可以將左值轉換為右值。使用這個函數并不能移動任何東西,而是和移動構造函數一樣都具有移動語義,將對象的狀態或者所有權從一個對象轉移到另一個對象,只是轉移,沒有內存拷貝。
當確定一個變量a后續不會再進行使用,并且需要將其賦值給另一個對象時,可以使用移動構造來轉移資源
Test a;
Test && b = a; // error
上面的操作是不可行的,因為a不是一個右值,要想調用Test的移動構造函數,就必須將a這個左值轉變為一個右值:使用move() 函數
Test a;
Test && b = move(a); // ok
std::move 基本等同于一個類型轉換:
static_cast<T&&>(lvalue)
3、foward
move將左值轉換為右值,foward可以滿足更多的情形
std::forward<T>(t);
- 當T為左值引用類型時,t將被轉換為T類型的左值
- 當T不是左值引用類型時,t將被轉換為T類型的右值
int a = 123;
foward<int&>(a); // a轉換為左值并返回
foward<int&&>(a); // a轉換為右值并返回
foward<int>(a); // a轉換為右值并返回
原文鏈接:https://blog.csdn.net/ulan420/article/details/126363446
相關推薦
- 2022-10-27 Kotlin?Flow操作符及基本使用詳解_Android
- 2022-09-21 python裝飾器底層原理詳解_python
- 2022-05-02 Entity?Framework中執行sql語句_實用技巧
- 2023-01-28 Python多線程與同步機制淺析_python
- 2023-04-20 使用replaceAll()方法實現數字千分位逗號分隔
- 2022-05-27 從零開始學Golang的接口_Golang
- 2023-05-06 Flutter學習之SliverList和SliverGird的使用詳解_Android
- 2022-05-31 jQuery實現側邊導航欄及滑動電梯效果(仿淘寶)_jquery
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支