C++: 左值引用和右值引用

目錄

概念:

理解:

?左值引用,右值引用

?左值引用能否給右值取別名?

右值引用能否給左值取別名?

引用的意義是什么?

左值和右值對自定義類型有什么區別嗎?

move的妙用!

沒有優化的左值傳輸:

?臨時變量是必然產生的!

?右值引用本身是左值!

主要原因:

右值引用的底層 和左值引用的底層:?

右值能否被改變?

概念:

傳統的C++語法中就有引用的語法,而C++11中新增了的右值引用語法特性,所以從現在開始我們 之前學習的引用就叫做左值引用。無論左值引用還是右值引用,都是給對象取別名。

什么是左值?什么是左值引用?

左值是一個表示數據的表達式(如變量名或解引用的指針),我們可以獲取它的地址+可以對它賦 值,左值可以出現賦值符號的左邊,右值不能出現在賦值符號左邊。

定義時const修飾符后的左 值,不能給他賦值,但是可以取它的地址。

左值引用就是給左值的引用,給左值取別名。

int main()
{// 以下的p、b、c、*p都是左值
int* p = new int(0);int b = 1;const int c = 2;// 以下幾個都是常見的右值
10;x + y;fmin(x, y);return 0;}

理解:

在以往較為淺薄的理解中,左值是可以進行修改的,右值是無法進行修改的

例如,圖中的a是變量可以進行修改是左值,但10是常數不能進行修改是右值,但不完全是這樣的結果:又如下圖所示,a在第一行代碼中是左值,在第二行代碼中又充當了右值,所以左值和右值不能如此輕易的劃分。

又如:加上了const的c是不允許被修改的,所以c是左值還是右值?答案是:c是左值!

因此,最后我們可以總結出一個結論,?可以取地址的是左值,不能取地址的是右值。

同時我們也需要注意,左值代表的不一定是一個數值,也可也是一個表達式。

例如:

*p 
*p 是一個左值vector<int> v(10,1);
v[1];
v[1] 是一個左值

凡是能取到地址的都算是左值!?

而右值就是取不到地址的,同樣右值也可以是一個表達式,且同時,臨時變量、匿名對象、臨時對象統統都是右值!

都是右值?

?左值引用,右值引用

引用就是取別名!左值引用就是給左值取別名,右值引用取別名!

int main()
{// 以下的p、b、c、*p都是左值
int* p = new int(0);int b = 1;const int c = 2;// 以下幾個是對上面左值的左值引用int*& rp = p;int& rb = b;const int& rc = c;int& pvalue = *p;double x = 1.1, y = 2.2;
// 以下幾個都是常見的右值
10;x + y;fmin(x, y);
// 以下幾個都是對右值的右值引用int&& rr1 = 10;double&& rr2 = x + y;double&& rr3 = fmin(x, y);
// 這里編譯會報錯:error C2106: “=”: 左操作數必須為左值10 = 1;x + y = 1;fmin(x, y) = 1;return 0;
}

?左值引用能否給右值取別名?

答案是不可以!但是加上const可以!

右值引用能否給左值取別名?

答案也是不可以!但是需要把左值加上move進行使用后才行!

所以左右值引用 可以對左右值進行取別名,但是要有條件!

引用的意義是什么?

  • 減少拷貝!提高效率!傳值、傳參、傳引用返回 都可以使用引用,這是左值引用的常見場景!
  • 但是左值引用沒有徹底解決返回值的問題,右值引用就是修補這一塊內容。
  • 因為如果是一個臨時對象,或者局部對象,則不能使用引用返回!因為出了作用域地址就會被銷毀,所以沒有用!而這種問題也不能直接使用右值引用進行返回,右值引用返回不是這樣用的!?

例如:

在主函數調用的時候,會在返回的時候進行臨時變量的構造然后再加上拷貝構造把數值從臨時變量中進行拷貝導賦值變量中,然后C++11后面優化成了一個直接獲取!

?這里無論是加左值引用還是右值引用都沒有效果且會報錯,因為str是局部變量被銷毀了!地址不存在了!因為出作用域了!

為了解決這種問題,增加一個右值引用的構造函數,而被右值引用修飾的構造叫做移動構造!

有了移動構造,編譯器會進行選擇,如果返回的時候是左值,那么編譯器就會去選擇拷貝構造,如果是右值,那么就會 選擇移動構造

左值和右值對自定義類型有什么區別嗎?

自定義類型的右值基本都是匿名對象、傳值返回的臨時對象。

然后右值又有細分,分為純右值和將亡值,基本上內置類型的右值都是純右值,而自定義類型的右值基本都是將亡值。

對于局部變量來說,它的左值只能是老實的開辟空間然后被利用完被拷貝完后銷毀空間,

而對于局部變量來說,它的右值(將亡值),它會利用空間! 將拷貝數值的空間和臨時變量的空間進行交換!

?有了移動構造后,在傳值時,會強行把左值變成右值,強行使用了move (可以不在返回時加上move 編譯器會做處理!)/可以看出str雖然是左值,但是和將亡值沒什么區別

?然后會調用兩次移動構造,但是編譯器直接轉移資源,一步到位!以前需要進行拷貝,但是右值的移動構造,將被賦值的數值強行和右值進行交換!

移動構造為什么叫移動構造,是因為它移動將亡值對象的資源!!!!把將亡值的資源轉移到被賦值調用的數據上!

嚴格來說,移動構造是延長了將亡值 所占據的資源數據的生命周期,而不是延長了將亡值所處在空間地址的生命周期。因為是轉移資源,所以移動構造的代價是極低的!

move的妙用!

可以看出s1的數據被移動到了s3 這就是move的功能!??

沒有優化的左值傳輸:

沒有優化的傳輸其實就是仙拷貝構造在賦值拷貝,就如下圖中的寫法,導致編譯器無法進行優化!

?優化:進行優化的左值傳輸!一次構造和一次拷貝構造,最后被編譯器優化成了一次拷貝構造!

?臨時變量是必然產生的!

?臨時對象是必然產生的,這個臨時對象是在寄存器的,但是寄存器非常的小,所以當對象數據過大時,會把臨時對象放到兩個數據的棧幀中:如下圖所示的綠色框框就是處在main和to_string兩個棧幀之間!

這種編譯器無法進行優化的,可以使用move進行轉化成移動構造函數,將其變成一次移動構造,一次移動賦值!

str在傳輸時會給一個臨時對象,然后把臨時對象的數據(空)的數據和 傳輸的數據進行數據之間的交換,然后在臨時賦值的時候,因為在賦值之前進行初始化,所以會把初始化的那個空間和臨時對象內部的數據再一次進行交換,然后完成移動賦值!

?右值引用本身是左值!

右值和右值引用,求s1是右值還是左值?左值!已知std::string(“11111111”)是右值

但是右值引用是左值!有地址!右值引用本身是左值!

主要原因:

右值有一個特點,本身是不能改變的,因為如果使用了別名,那如果別名也不能改變,那如何做資源轉移?

可以看出右值的資源轉移主要是因為swap如轉移的過程中數值不能進行改變,也就是右值引用的數據不能改變,那么將無法進行資源的轉移!所以也就可以得出,右值引用是左值!

右值引用的底層 和左值引用的底層:?

右值引用和左值引用的底層都是指針,都是取匿名空間的地址!所以右值真的沒有地址嗎?那右值存哪里?總要存儲吧!所以右值是有地址的,只是不能拿取這個地址罷了!取不到這個地址罷了!?

右值能否被改變?

s5是可以左值引用s1的!但是s6是不能直接左值引用的!但是可以使用強制轉化:

可以資源轉移到s7!所以右值能否改變呢!可以的!如果不用強轉呢?

先給一個右值引用,然后在左值引用,本質就是右值引用底層是指針,且底層還是有空間存儲的!

和上面的s5和s1的操作一樣!類似于交換!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/40443.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/40443.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/40443.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LLMs之CriticGPT:CriticGPT的簡介、安裝和使用方法、案例應用之詳細攻略

LLMs之CriticGPT&#xff1a;CriticGPT的簡介、安裝和使用方法、案例應用之詳細攻略 目錄 CriticGPT的簡介 1、簡介 2、CriticGPT的方法 2.1、CriticGPT的訓練方法 2.2、CriticGPT的批評生成方法 3、局限性 4、后續步驟 CriticGPT的安裝和使用方法 CriticGPT的案例應用…

“proxy_pass“ directive is duplicate

后面發現是nginx.conf里面proxy pass這里有兩個&#xff0c;注釋其中一個并重新運行即可&#xff01;

AI并不是開發者的敵人,而是幫助他們實現更高效工作的得力助手。

AI是在幫助開發者還是取代他們&#xff1f; 在軟件開發領域&#xff0c;生成式人工智能&#xff08;AIGC&#xff09;正在改變開發者的工作方式。無論是代碼生成、錯誤檢測還是自動化測試&#xff0c;AI工具正在成為開發者的得力助手。然而&#xff0c;這也引發了對開發者職業前…

基于主流SpringBoot進行JavaWeb開發的學習路線

目錄 一、學習路線 &#xff08;1&#xff09;第一部分&#xff08;Web前端開發的技術棧&#xff09; &#xff08;2&#xff09;第二部分&#xff08;Web后端開發&#xff09; 二、學習之后必備的技能 三、學習Web開發的基礎與未來的收獲 學完這一類知識目標&#xff1a;…

Mybatis-01 原理

一. JDBC式編程 在 jdbc 編程中&#xff0c;我們最常用的是 PreparedStatement 式的編程&#xff0c;我們看下面這個例子&#xff1b; Connection conn null; PreparedStatement ps null; ResultSet rs null;try {// 1. 注冊驅動Class.forName("com.mysql.jdbc.Drive…

Sping源碼總覽

源碼地址&#xff1a;https://github.com/spring-projects/spring-framework 倉庫地址&#xff1a;https://gitcode.net/qq_42665745/spring/-/tree/master 文章目錄如下&#xff1a; 實現一個簡單的Bean容器Bean 的定義、注冊、獲取Bean有參構造實例化Bean屬性注入資源加載器…

C++11使用std::future和std::promise實現線程同步和異步通信

std::future 和 std::promise 是 C11 引入的標準庫特性&#xff0c;用于實現線程間的異步通信和同步。它們提供了一種機制&#xff0c;使一個線程能夠生成一個值或異常&#xff0c;并讓另一個線程獲取這個值或異常。 (線程A中設置結果) std::promise 用于設置異步操作的結果(線…

【Jupyter Notebook與Git完美融合】在Notebook中駕馭版本控制的藝術

標題&#xff1a;【Jupyter Notebook與Git完美融合】在Notebook中駕馭版本控制的藝術 Jupyter Notebook是一個流行的開源Web應用程序&#xff0c;允許用戶創建和共享包含實時代碼、方程、可視化和解釋性文本的文檔。而Git是一個廣泛使用的分布式版本控制系統&#xff0c;用于跟…

關于C#在WPF中如何使用“抽屜”控件

關于C#在WPF中如何使用“抽屜”控件 1.前提準備2.XAML代碼3.對應的C#代碼4.顯示效果1.前提準備 需要引用MaterialDesign控件庫,關于如何引用,請參照文章——關于C#如何引用MaterialDesign控件庫 2.XAML代碼 <Window x:Class="MaterialDesign_Test.MainWindow"…

化身成羊:關于羊的詞群探析

在西方的神話故事中&#xff0c;像主神宙斯&#xff0c;或者基督教義中的上帝&#xff0c;通常都有化身成羊的形象。 那為什么會這樣呢&#xff1f; 一、什么是神話(myth)&#xff1f; 神話&#xff0c;正式的用詞是 mythology&#xff1a; mythology n.神話&#xff1b;神話…

Http接口RestSharp中StatusCode返回0, 但服務器或本地postman獲取應答正常(C#)

我的本地和其他服務器用同一段代碼都可以訪問&#xff1a; 原代碼&#xff1a; RestClient client new RestClient(url); client.Timeout -1; RestRequest request new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer " acc…

Echarts中的折線圖,多個Y軸集中在左側(在Vue中使用多個Y軸的折線圖)

簡述&#xff1a;在 ECharts 中&#xff0c;創建一個帶有多個 Y 軸的折線圖&#xff0c;并且將這些 Y 軸都集中顯示在圖表的左側&#xff0c;可以通過合理配置 yAxis 和 series 的屬性來實現。簡單記錄 一. 函數代碼 drawCarNumEcs() {// 初始化echarts圖表,并綁定到id為"…

網絡安全設備——探針

網絡安全設備探針是一種專門用于網絡安全領域的工具&#xff0c;它通過對網絡流量進行監控和分析&#xff0c;幫助發現和防止網絡攻擊。以下是對網絡安全設備探針的詳細解釋&#xff1a; 定義與功能 定義&#xff1a;網絡安全設備探針是一種設備或軟件&#xff0c;它通過捕獲…

【docker】運行階段遇到的問題

目錄 1、查詢docker 下掛載了哪些工具 2、docker中的簡單命令 3、實際場景應用&#xff08;redis&#xff09; 目前工作中僅用到了redis,所以沒有太多經驗可以交流&#xff0c;暫時僅將我目前遇到的進行發布。還請見諒。 1、查詢docker 下掛載了哪些工具 docker ps -a 或者…

Vue組件如何“傳話”?這里有個小秘訣!

?&#x1f308;個人主頁&#xff1a;前端青山 &#x1f525;系列專欄&#xff1a;vue篇 &#x1f516;人終將被年少不可得之物困其一生 依舊青山,本期給大家帶來vue篇專欄內容:vue-組件通信 目錄 Vue組件通信 &#xff08;1&#xff09; props / $emit 1. 父組件向子組件傳…

適合職場小白的待辦事項管理方法和工具

剛入職場那會兒&#xff0c;我每天都像只無頭蒼蠅&#xff0c;忙得團團轉卻效率低下。待辦事項像潮水般涌來&#xff0c;會議、報告、客戶跟進……每一項都像是懸在頭頂的利劍&#xff0c;讓我焦慮不堪。我深知&#xff0c;管理好待辦事項是職場生存的必修課&#xff0c;但該如…

內衣洗衣機哪個牌子好用?傾力推薦四大熱門產品,質量放心

在當今社會&#xff0c;內衣洗衣機已經成為每個家庭必不可少的家電之一。但由于市場上的內衣洗衣機品牌和型號繁多&#xff0c;對于消費者來說&#xff0c;選擇一款實用、性價比高的內衣洗衣機是非常重要的。那么&#xff0c;內衣褲洗衣機哪個品牌最好&#xff1f;接下來我將會…

框架為我們做了什么?

1. SpringBoot 1.1 web服務器 Spring Boot 的 web 服務器原理主要基于其嵌入式服務器的概念&#xff0c;這意味著它內嵌了一個 web 服務器&#xff0c;無需部署到外部服務器上。Spring Boot 內嵌了如 Tomcat、Jetty 或 Undertow 等 servlet 容器。 1.2 servlet Servlet&…

【鴻蒙學習筆記】創建自定義組件

官方文檔&#xff1a;創建自定義組件 目錄標題 自定義組件的基本結構&#xff11;?struct 自定義組件名 {...}&#xff20;ComponentEntry &#xff11;? &#xff12;? &#xff13;? &#xff14;? &#xff15;? &#xff16;? &#xff17;? &#xff18;? &…

Python | Leetcode Python題解之第206題反轉鏈表

題目&#xff1a; 題解&#xff1a; # Definition for singly-linked list. # class ListNode: # def __init__(self, val0, nextNone): # self.val val # self.next next class Solution:def reverseList(self, head: Optional[ListNode]) -> Optio…