C++11笑傳之引用

C++11

  • 前言
  • 列表初始化
    • {}進行初始化
    • initializer_list
  • 右值引用和移動語義
    • 左值與右值
    • 左值引用與右值引用
    • 引用延長生命周期
    • 右值引用和移動語義的使用場景
    • 左值引用
    • 移動構造和移動賦值
  • 右值引用在容器插入的提效
  • 引用折疊
    • 萬能折疊
    • 完美轉發

前言

C++11是C++繼98后的更新,其更新了許多內容,是非常重要的,除了我們前文所提到的范圍for和auto,還有許多新的東西,對于C++11完全可以把它當成新的語言進行學習

列表初始化

{}進行初始化

C++11以后想統?初始化?式,試圖實現?切對象皆可?{}初始化,{}初始化也叫做列表初始化。
內置類型?持,?定義類型也?持,?定義類型本質是類型轉換,中間會產?臨時對象,最后優化了以后變成直接構造。
{}初始化的過程中,可以省略掉=

int x2 { 2 };
Date d6 { 2024, 7, 25 };

C++11列表初始化的本意是想實現?個?統?的初始化?式,其次他在有些場景下帶來的不少便利,如容器push/inset多參數構造的對象時,{}初始化會很方便

initializer_list

initializer_list是C++11之后提到的一個類,這個類的本質是底層開?個數組,將數據拷貝過來,initializer_list內部有兩個指針分別指向數組的開始和結束。initializer_list與剛剛提到的{}初始化是不一樣的,{}是基于構造函數,也就是說需要初始化每一個值都是需要對應的構造函數的。這樣對于初始化容器就很不方便,例如初始化vector里的數,總不能寫N個構造函數吧

vector<int> v1 ={1,2,3}

容器?持?個std::initializer_list的構造函數,也就?持任意多個值構成的 {x1,x2,x3…} 進?初始化。STL中的容器?持任意多個值構成的 {x1,x2,x3…} 進?初始化,就是通過initializer_list的構造函數?持的。

右值引用和移動語義

左值與右值

左值是?個表?數據的表達式(如變量名或解引用的指針),?般是有持久狀態,存儲在內存中,我們可以獲取它的地址,左值可以出現賦值符號的左邊,也可以出現在賦值符號右邊。定義時const修飾符后的左值,不能給他賦值,但是可以取它的地址。
右值也是?個表?數據的表達式,要么是字面值常量、要么是表達式求值過程中創建的臨時對象等,右值可以出現在賦值符號的右邊,但是不能出現出現在賦值符號的左邊,右值不能取地址。
左值與右值的核心區別就是能否取地址

左值引用與右值引用

int& a = x;int&& b = y;

第一個語句就是左值引用,第二個就是右值引用。
左值引用不能直接引用右值,但是const左值引用可以引用右值
右值引用不能直接引用左值,但是右值引用可以引用move(左值)
move的作用就是強制轉化為右值,但是屬性還是左值的屬性,只是類型強制轉換。但是除非確定需要將左值轉為右值,否則不要用move,因為move之后左值的資源會被竊取掉,那么左值又是會一直存在的,就會導致左值是一個懸空指針
需要注意的是變量表達式都是左值屬性,也就意味著?個右值被右值引?綁定后,右值引?變量變量表達式的屬性是左值,不然在后續進行移動語義的時候,如果右值引用后的屬性是右值屬性,那就無法修改了,也就無法移動了。

int* p = new int(0);
int b = 1;
const int c = b;
*p = 10;
string s("111111");
s[0] = 'x';
double x = 1.1, y = 2.2;
// 左值引?給左值取別名
int& r1 = b;
int*& r2 = p;
int& r3 = *p;
string& r4 = s;
char& r5 = s[0];
// 右值引?給右值取別名
int&& rr1 = 10;
double&& rr2 = x + y;
double&& rr3 = min(x, y);
string&& rr4 = string("11111");
// 左值引?不能直接引?右值,但是const左值引?可以引?右值
const int& rx1 = 10;
const double& rx2 = x + y;
const double& rx3 = min(x, y);
const string& rx4 = string("11111");
// 右值引?不能直接引?左值,但是右值引?可以引?move(左值)
int&& rrx1 = move(b);
int*&& rrx2 = move(p);
int&& rrx3 = move(*p);
string&& rrx4 = move(s);
string&& rrx5 = (string&&)s;

引用延長生命周期

右值引?可?于為臨時對象延??命周期,const 的左值引?也能延?臨時對象?存期,但const對象?法被修改。

右值引用和移動語義的使用場景

左值引用

左值引?主要使?場景是在函數中左值引?傳參和左值引?傳返回值時減少拷?,同時還可以修改實參和修改返回對象的值。左值引?已經解決?多數場景的拷?效率問題,但是有些場景不能使?傳左值引?返回,如addStrings和generate函數,C++98中的解決?案只能是被迫使?輸出型參數解決。那么C++11以后這?可以使?右值引?做返回值解決嗎?顯然是不可能的,因為這?的本質是返回對象是?個局部對象,函數結束這個對象就析構銷毀了,右值引?返回也?法改變對象已經析構銷毀的事實。

移動構造和移動賦值

移動構造函數是?種構造函數,類似拷?構造函數,移動構造函數要求第?個參數是該類類型的引?,但是不同的是要求這個參數是右值引?,如果還有其他參數,額外的參數必須有缺省值。
移動賦值是?個賦值運算符的重載,他跟拷?賦值構成函數重載,類似拷?賦值函數,移動賦值函數要求第?個參數是該類類型的引?,但是不同的是要求這個參數是右值引?。
對于像string/vector這樣的深拷貝的類或者包含深拷貝的成員變量的類,移動構造和移動賦值才有意義,因為移動構造和移動賦值的第?個參數都是右值引?的類型,他的本質是要“竊取”引?的右值對象的資源,?不是像拷?構造和拷?賦值那樣去拷?資源,從提?效率。
在這里插入圖片描述
必須得有移動構造函數才可以出現移動構造

string(string&& s)
{cout << "string(const string& s) -- 移動構造" << endl;this->swap(s);
}

移動構造是將右值與當前值進行交換,將有用的資源交換給需要的變量,這樣相比與之前的拷貝構造出一個臨時變量,再將臨時變量拷貝構造給所需要的變量,效率要高很多

右值引用在容器插入的提效

? 查看STL文檔我們發現C++11以后容器的push和insert系列的接?否增加的右值引?版本
在這里插入圖片描述

? 當實參是?個左值時,容器內部繼續調?拷貝構造進?拷貝,將對象拷貝到容器空間中的對象
? 當實參是?個右值,容器內部則調?移動構造,右值對象的資源到容器空間的對象上

引用折疊

? C++中不能直接定義引?的引?如 int& && r = i; ,這樣寫會直接報錯,通過模板或 typedef中的類型操作可以構成引用的引用。
? 通過模板或 typedef 中的類型操作可以構成引用的引用時,這時C++11給出了?個引用折疊的規則:右值引用的右值引用折疊成右值引用,所有其他組合均折疊成左值引用。

typedef int& lref;
typedef int&& rref;
int n = 0;
lref& r1 = n; // r1 的類型是 int&
lref&& r2 = n; // r2 的類型是 int&
rref& r3 = n; // r3 的類型是 int&
rref&& r4 = 1; // r4 的類型是 int&&

萬能折疊

template<class T>
void Function(T&& t)
{}

以上代碼就是萬能折疊,如果傳的是int右值,T就會被識別成int,如果傳的是int左值,T就會被識別成int&,這樣就實現了傳左值就是左值引用的參數,傳右值就是右值引用的參數

完美轉發

因為變量表達式的屬性都是左值,即雖然傳的是右值,在萬能折疊下,t被識別成右值引用的類型,但由于t是變量表達式,所以如果把t傳給其他函數,就會把其他函數的形參的屬性變為左值,所以出現完美轉發來解決這一問題。

template<class T>
void Function(T&& t)
{// 完美保持他的屬性傳參Fun(forward<T>(t));
}

完美轉發forward是一個函數模版,可以把他與move相對應,move是將左值強制轉化為右值,但是屬性并不會發生改變,只是告訴編譯器該左值是可以被竊取的,而forward是可以保持該對象的屬性的,即t如果是右值引用,就會保持為右值引用,如果是左值,就會保持為左值

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

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

相關文章

瀚高數據庫提交數據后,是否需要COMMIT(APP)

文章目錄環境癥狀問題原因解決方案報錯編碼環境 系統平臺&#xff1a; 版本&#xff1a;5.6.5,4.5 癥狀 瀚高數據庫提交數據后&#xff0c;是否需要commit&#xff0c;瀚高數據庫是否有配置項。 問題原因 瀚高數據庫默認自動COMMIT&#xff08;提交數據&#xff09;&#…

深大計算機游戲開發實驗三

主要步驟主角飛船的創建和移動邊界設置以及護盾設置創建敵機自動生成敵機圖層設置彈丸設置武器創建不同發射模式管理競態條件擊敗敵機掉落升級道具不同敵機的生成分值顯示實現退出游戲界面之后進入游戲的最高記錄重置游戲界面失敗后重新加載最記錄不會重置任何時候在游戲界面按…

詳解緩存淘汰策略:LRU

文章目錄緩存淘汰策略LRU核心結構核心操作流程局限性源碼走讀AddGet緩存淘汰策略 緩存淘汰策略的存在是為了解決 緩存容量有限性 和 高緩存命中率 之間的矛盾。其核心目標是在有限的緩存空間內&#xff0c;盡可能提高緩存命中率 緩存容量有限性&#xff1a;緩存&#xff08;例…

什么是 Bootloader?怎么把它移植到 STM32 上?

一、Bootloader 是啥&#xff1f;它都干了些啥&#xff1f;想象一下你的 MCU&#xff08;比如 STM32&#xff09;是一個小機器人&#xff0c;上電之后第一件事&#xff0c;它不會立馬開始“干正事”&#xff08;運行你的主程序&#xff09;&#xff0c;而是先去運行一個“開場引…

無人機避障——感知篇(Ego_Planner_v2中的滾動窗口實現動態實時感知建圖grid_map ROS節點理解與參數調整影響)

處理器&#xff1a;Orin nx 雙目視覺傳感器&#xff1a;ZED2 實時感知建圖方法&#xff1a;Vins Fusion Raycast &#xff08;VIO與射線投影法感知定位加建圖方法&#xff09; 項目地址&#xff1a;https://github.com/ZJU-FAST-Lab/EGO-Planner-v2 【注意】&#xff1a;建…

26-計組-尋址方式

指令尋址與PC自增一、指令尋址方式定義&#xff1a;尋找下一條將要執行的指令地址的過程。 核心部件&#xff1a;程序計數器&#xff08;PC&#xff09;&#xff0c;用于指示待執行指令的地址。 執行流程&#xff1a;CPU根據PC值從主存取指令。取指后&#xff0c;PC自動自增&am…

生成式對抗網絡(GAN)模型原理概述

生成對抗網絡&#xff08;Generative Adversarial Network, GAN&#xff09;是一種通過對抗訓練生成數據的深度學習模型&#xff0c;由生成器&#xff08;Generator&#xff09;和判別器&#xff08;Discriminator&#xff09;兩部分組成&#xff0c;其核心思想源于博弈論中的零…

Vue和Element的使用

文章目錄1.vue 腳手架創建步驟2.vue項目開發流程3.vue路由4.Element1.vue 腳手架創建步驟 創建一個文件夾 vue雙擊進入文件夾,在路徑上輸入cmd輸入vue ui, 目的:調出圖形化用戶界面點擊創建 9. 10.在vscode中打開 主要目錄介紹 src目錄介紹 vue項目啟動 圖形化界面中沒有npm…

如何設置直播間的觀看門檻,讓直播間安全有效地運行?

文章目錄前言一、直播間觀看門檻有哪幾種形式&#xff1f;二、設置直播間的觀看門檻&#xff0c;對直播的好處是什么三、如何一站式實現上述功能&#xff1f;總結前言 打造一個安全、高效、互動良好的直播間并非易事。面對海量涌入的觀眾&#xff0c;如何有效識別并阻擋潛在的…

【SkyWalking】配置告警規則并通過 Webhook 推送釘釘通知

&#x1f9ed; 本文為 【SkyWalking 系列】第 3 篇 &#x1f449; 系列導航&#xff1a;點擊跳轉 【SkyWalking】配置告警規則并通過 Webhook 推送釘釘通知 簡介 介紹 SkyWalking 告警機制、告警規則格式以及如何通過 webhook 方式將告警信息發送到釘釘。 引入 服務響應超時…

關于 驗證碼系統 詳解

驗證碼系統的目的是&#xff1a;阻止自動化腳本訪問網頁資源&#xff0c;驗證訪問者是否為真實人類用戶。它通過各種測試&#xff08;圖像、行為、計算等&#xff09;判斷請求是否來自機器人。一、驗證碼系統的整體架構驗證碼系統通常由 客戶端 服務端 風控模型 數據采集 四…

微服務集成snail-job分布式定時任務系統實踐

前言 從事開發工作的同學&#xff0c;應該對定時任務的概念并不陌生&#xff0c;就是我們的系統在運行過程中能夠自動執行的一些任務、工作流程&#xff0c;無需人工干預。常見的使用場景包括&#xff1a;數據庫的定時備份、文件系統的定時上傳云端服務、每天早上的業務報表數…

依賴注入的邏輯基于Java語言

對于一個廚師&#xff0c;要做一道菜。傳統的做法是&#xff1a;你需要什么食材&#xff0c;就自己去菜市場買什么。這意味著你必須知道去哪個菜市場、怎么挑選食材、怎么討價還價等等。你不僅要會做菜&#xff0c;還要會買菜&#xff0c;職責變得復雜了。 而依賴注入就像是有一…

skywalking鏡像應用springboot的例子

目錄 1、skywalking-ui連接skywalking-oap服務失敗問題 2、k8s環境 檢查skywalking-oap服務狀態 3、本地iidea啟動服務連接skywalking oap服務 4、基于apache-skywalking-java-agent-9.4.0.tgz構建skywalking-agent鏡像 4.1、Dockerfile內容如下 4.2、AbstractBuilder.M…

3. java 堆和 JVM 內存結構

1. JVM介紹和運行流程-CSDN博客 2. 什么是程序計數器-CSDN博客 3. java 堆和 JVM 內存結構-CSDN博客 4. 虛擬機棧-CSDN博客 5. JVM 的方法區-CSDN博客 6. JVM直接內存-CSDN博客 7. JVM類加載器與雙親委派模型-CSDN博客 8. JVM類裝載的執行過程-CSDN博客 9. JVM垃圾回收…

UnityShader——SSAO

目錄 1.是什么 2.原理 3.各部分解釋 2.1.從屏幕空間到視圖空間 2.2.以法線半球為基&#xff0c;獲取隨機向量 2.3.應用偏移&#xff0c;并將其轉換為uv坐標 2.4.獲取深度 2.5.比較并計算貢獻 2.6.最后計算 4.改進 4.1.平滑過渡 4.2.模糊 5.變量和語句解釋 5.1._D…

【設計模式】外觀模式(門面模式)

外觀模式&#xff08;Facade Pattern&#xff09;詳解一、外觀模式簡介 外觀模式&#xff08;Facade Pattern&#xff09; 是一種 結構型設計模式&#xff0c;它為一個復雜的子系統提供一個統一的高層接口&#xff0c;使得子系統更容易使用。 外觀模式又稱為門面模式&#xff0…

【6.1.1 漫畫分庫分表】

漫畫分庫分表 “數據量大了不可怕&#xff0c;可怕的是不知道如何優雅地拆分。” &#x1f3ad; 人物介紹 架構師老王&#xff1a;資深數據庫架構專家&#xff0c;精通各種分庫分表方案Java小明&#xff1a;對分庫分表充滿疑問的開發者ShardingSphere師傅&#xff1a;Apache S…

Tomcat問題:啟動腳本startup.bat中文亂碼問題解決

一、問題描述 我們第一次下載或者打開Tomcat時可能在控制臺會出現中文亂碼問題二、解決辦法 我的是8.x版本的tomcat用notepad打開&#xff1a;logging.properties 找到&#xff1a;java.util.logging.ConsoleHandler.encoding設置成GBK&#xff0c;重啟tomcat即可

Linux中Gitee的使用

一、Gitee簡介&#xff1a;Gitee&#xff08;碼云&#xff09;是中國的一個代碼托管和協作開發平臺&#xff0c;類似于GitHub或GitLab&#xff0c;主要面向開發者提供代碼管理、項目協作及開源生態服務。適用場景個人開發者&#xff1a;托管私有代碼或參與開源項目。中小企業&a…