C++11?右值引用的使用場景分析
前言
c++11中新增了右值引用的語法,本章主要說明左值引用和右值引用的使用場景
在我們了解左值引用和右值引用前,我們要先來理解一下左值和右值分別是什么
1.左值and右值
左值是一個表示數(shù)據(jù)的表達式,我們可以獲取它的地址,有持久狀態(tài)存儲在內(nèi)存當(dāng)中,變量名,指針等,只要是可以取到地址的表達式都是左值
右值也是一個數(shù)據(jù)表達式,一般是字面常量或者創(chuàng)建的臨時對象
核心區(qū)別:是否可以拿到地址,可以取地址就是左值 取不到地址就是右值
2.左值引用and右值引用
我們知道引用其實就是起了一個別名 左值引用和右值引用也就是起別名
一個& 就是左值引用 兩個&&就是右值引用
注意:左值引用不能直接引用右值 const左值可以引用右值
右值引用不能直接引用左值 右值引用可以引用move(左值)
move是一個函數(shù) 底層我們可以理解就是將左值強轉(zhuǎn)成右值 但它的屬性還是左值
引用可以延長生命周期
我們知道臨時變量的生命周期很短,只有執(zhí)行的那一行代碼
const左值可以延長生命周期 右值引用可以延長生命周期
但是普通左值引用不可以延長生命周期,這是因為臨時對象是右值,普通左值引用綁定右值,就可能會出現(xiàn)對已經(jīng)銷毀的對象做無效引用
注意:這里的延長生命周期是只在當(dāng)前的棧幀有效,一旦函數(shù)運行完畢,進行釋放,被延長的生命周期的臨時對象也就被銷毀了,延長的生命周期只在當(dāng)前的作用域有效!?。?!
3.參數(shù)匹配
c++98當(dāng)我們實現(xiàn)一個const左值引用作為參數(shù),那么傳左值和右值都可以
c++11新增了右值引用,當(dāng)我們進行傳參,編譯器就會找到相對最匹配的函數(shù)繼續(xù)傳參??!
右值引用變量在用于表達式的時候?qū)傩允亲笾?/p>
4.左值引用和右值引用的使用場景
左值引用的使用場景:
當(dāng)函數(shù)的參數(shù)是左值引用 可以減少拷貝 因為它只是一個別名 左值引用傳返回值得到時候 也可以減少拷貝 也可以修改實參 左值引用可以解決大量的拷貝效率問題 但是有些場景不能使用傳左值引用返回
我們來舉個例子 就是如果在當(dāng)前棧幀中創(chuàng)建臨時對象,我們就需要傳值返回,這種消耗是很大的!
在c++11 右值引用還沒有出來時,編譯器對此進行了優(yōu)化,不同的編譯器優(yōu)化可能不同
我們來看一下編譯器優(yōu)化 雖然說最終優(yōu)化只有一次構(gòu)造 但是還是有構(gòu)造 會造成資源消耗
還有一種情況 拷貝構(gòu)造+拷貝賦值
針對于以上的這種情況 我們使用C++11的右值使用就可以很好的解決這個問題
5.移動構(gòu)造和移動賦值
移動構(gòu)造類似拷貝構(gòu)造,移動構(gòu)造函數(shù)的第一個參數(shù)必須是該類類型的右值引用
這個構(gòu)造不同于拷貝構(gòu)造,拷貝構(gòu)造會進行深拷貝,移動構(gòu)造是資源進行轉(zhuǎn)移!!不會進行深拷貝
// 移動構(gòu)造 string(string&& s) { cout << "string(string&& s) -- 移動構(gòu)造" << endl; swap(s); }
就上述場景來看,無論編譯器怎么優(yōu)化,最終還是有一次拷貝,但c++11引入了右值引用,就可以很好的解決這個問題,這里的swap就是進行資源轉(zhuǎn)移
移動賦值是賦值運算符重載 移動賦值函數(shù)要求第一個參數(shù)必須是該類型的右值引用
它的本質(zhì)也是進行資源轉(zhuǎn)移 并不會進行深拷貝,這樣就可以減少深拷貝 提高資源利用效率
/// 移動賦值 string& operator=(string&& s) { cout << "string& operator=(string&& s) -- 移動賦值" << endl; swap(s); return *this; }
6.引用折疊and萬能引用
C++11中不可以直接將左值引用和右值引用寫在一起 int& && x = i; 這種寫法是錯誤的
我們需要通過模版或者typedef的操作 構(gòu)成引用的引用
C++11規(guī)定 右值引用的右值引用折疊后是右值引用 其他的組合折疊后都是左值引用
我們通過一些例子來理解一下:
萬能引用其實就是一個模版 將參數(shù)設(shè)計成T&& 既可以接受左值引用又可以接受右值引用
template<class T> void Function(T&& t) { Fun(t); }
7.完美轉(zhuǎn)發(fā)
完美轉(zhuǎn)發(fā)的核心要點就是保持當(dāng)前對象的屬性
template<class T> void Function(T&& t) { //Fun(t); Fun(forward<T>(t)); }
完美轉(zhuǎn)發(fā)的使用場景:我們知道變量表達式都是左值屬性 當(dāng)一個右值被右值引用綁定后 右值引用變量表達式的屬性是左值 Function的t的屬性是左值 將t傳給Fun,那么只會匹配左值引用的Fun函數(shù),代碼結(jié)果就會出現(xiàn)錯誤 這個時候我們就需要使用完美轉(zhuǎn)發(fā)保持t的屬性
完美轉(zhuǎn)發(fā)forward的本質(zhì)是一個函數(shù)模版,核心是通過引用折疊實現(xiàn) 如果說傳給Function的實參是右值 T被推導(dǎo)int,不進行折疊,forward內(nèi)部t被轉(zhuǎn)換成右值引用進行返回 如果說傳給Function的實參是左值,T被推導(dǎo)int&,引用折疊左值引用,forward內(nèi)部t被強轉(zhuǎn)為左值引用返回
到此這篇關(guān)于C++11 右值引用的文章就介紹到這了,更多相關(guān)C++11 右值引用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言數(shù)據(jù)結(jié)構(gòu)之?dāng)U展字符詳解
掌握C語言數(shù)據(jù)結(jié)構(gòu)的關(guān)鍵在于理解其核心概念,擴展字符作為其中的重要一環(huán),對于編程人員來說至關(guān)重要,本指南將為您深入剖析擴展字符的相關(guān)知識,帶您輕松掌握C語言數(shù)據(jù)結(jié)構(gòu),讓我們一起探索這個令人著迷的領(lǐng)域吧!2024-03-03C語言實現(xiàn)跨文件傳輸數(shù)據(jù)的幾種方式
C語言是一種強大的、通用的編程語言,常用于系統(tǒng)級編程,包括硬件交互,如中斷處理和數(shù)據(jù)采集,在本文中,我們將深入探討如何使用C語言進行跨文件數(shù)據(jù)傳輸,文中有相關(guān)的代碼供大家參考,需要的朋友可以參考下2024-08-08C語言編程數(shù)據(jù)結(jié)構(gòu)的棧和隊列
本篇文章是C語言編程篇,主要為大家介紹C語言編程中的數(shù)據(jù)結(jié)構(gòu),詳細的講解了數(shù)據(jù)結(jié)構(gòu)的棧和隊列有需要的朋友可以借鑒參考下,希望可以有所幫助2021-09-09