日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

c语言 变量的左值和右值,C++雾中风景10:聊聊左值,纯右值与将亡值

發(fā)布時(shí)間:2024/4/20 c/c++ 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c语言 变量的左值和右值,C++雾中风景10:聊聊左值,纯右值与将亡值 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

C++11的版本在類型系統(tǒng)上下了很大的功夫,添加了諸如auto,decltype,move等新的關(guān)鍵詞來(lái)簡(jiǎn)化代碼的編寫(xiě)與降低閱讀代碼的難度。為了更好的理解這些新的語(yǔ)義,筆者確定通過(guò)幾篇文章來(lái)簡(jiǎn)單窺探一下C++類型系統(tǒng)的冰山一角,如果加深了對(duì)C++類型系統(tǒng)的理解,想必大家也能夠更好的應(yīng)用由C++11帶給我們的新"利器"。

1.左值與右值

左值(lvalue)和右值(rvalue)是C++類型系統(tǒng)之中的基礎(chǔ)概念,我們不需要了解這些基礎(chǔ)概念,同樣也能寫(xiě)出代碼。但是如果沒(méi)有弄清左右值的概念,對(duì)于許多C++高級(jí)特性的探索會(huì)一葉障目,所以筆者嘗試總結(jié)一下自己對(duì)于左值與右值的理解。

在C++11之前的版本,基本沿用了C語(yǔ)言之中對(duì)于左值與右值的定義,說(shuō)起來(lái)也很簡(jiǎn)單:“在C++之中的變量只有左值與右值兩種:其中凡是可以取地址的變量就是左值,而沒(méi)有名字的臨時(shí)變量,字面量就是右值”。 正是因?yàn)檫@兩種變量分別位于=的左右兩側(cè),所以被命名為左值與右值。下面,舉個(gè)栗子:

int x;

int y;

x = 1;

y = 2;

x = y;

y = x;

// 以下代碼有誤

3 = x;

x + y = 4;

通過(guò)上述的代碼我們可以快速的理解,顯然x,y作為變量可以存在=的左側(cè),而稱之為左值,而3,x + y作為字面量或中間結(jié)果,沒(méi)有辦法取得地址,則稱之為右值。 這里筆者也給一個(gè)簡(jiǎn)單判定的左右值的方式:

判斷能否取值的地址,能取地址的就是左值。

2.將亡值

其實(shí)上一節(jié)對(duì)于左值右值的描述,在我們編寫(xiě)絕大多數(shù)代碼的場(chǎng)景下并沒(méi)有什么影響。而在C++11擴(kuò)展了右值的的概念,將右值分為了純右值(pure rvalue)與將亡值(eXpiring Value)。純右值的概念等同于我們之前所理解的右值,指的是臨時(shí)變量或字面量值;而將亡值是C++11新引入的概念,它依托于右值。

在C++之中,使用左值去初始化對(duì)象或?yàn)閷?duì)象賦值時(shí),會(huì)調(diào)用拷貝構(gòu)造函數(shù)或賦值構(gòu)造函數(shù)。而使用一個(gè)右值來(lái)初始化或賦值時(shí),會(huì)調(diào)用移動(dòng)構(gòu)造函數(shù)或移動(dòng)賦值運(yùn)算符來(lái)移動(dòng)資源,從而避免拷貝,提高效率。 而將亡值可以理解為通過(guò)移動(dòng)構(gòu)造其他變量?jī)?nèi)存空間的方式獲取到的值。在確保其他變量不再被使用、或即將被銷(xiāo)毀時(shí),來(lái)延長(zhǎng)變量值的生命期。而實(shí)際上該右值會(huì)馬上被銷(xiāo)毀,所以稱之為:將亡值。

上述概念闡述的略微抽象,我們來(lái)看下面這段代碼:

這是我們簡(jiǎn)單定義的Time類,在類中我們定義了拷貝構(gòu)造函數(shù)和移動(dòng)構(gòu)造函數(shù):

class Time {

public:

int* hour;

int* minute;

int* second;

Time(int h, int m, int s) {

hour = new int(h);

minute = new int(m);

second = new int(s);

}

Time(const Time& t) {

cout << "copy" << endl;

hour = new int(*t.hour);

minute = new int(*t.minute);

second = new int(*t.second);

}

Time(Time&& t) noexcept:hour(t.hour),minute(t.minute),second(t.second) {

t.hour = nullptr;

t.minute = nullptr;

t.second = nullptr;

cout << "move" << endl;

}

~Time() {

cout << "call ~Time()" << endl;

delete hour;

delete minute;

delete second;

}

};

接下來(lái)我們執(zhí)行下面的代碼:

int main()

{

Time test(10,25,12);

Time test2(test);

return 0;

}

執(zhí)行結(jié)果:

copy

call ~Time()

call ~Time()

由上述代碼我們看到test2對(duì)象調(diào)用了拷貝構(gòu)造函數(shù)來(lái)構(gòu)造了新的對(duì)象,這個(gè)過(guò)程顯然是更占用內(nèi)存的。而接下來(lái),我們嘗試?yán)胢ove函數(shù)將test強(qiáng)行轉(zhuǎn)化為將亡值,來(lái)避免內(nèi)存重新分配的過(guò)程。但是之后我們也無(wú)法再訪問(wèn)test對(duì)象的內(nèi)容了,因?yàn)槎荚谝苿?dòng)構(gòu)造函數(shù)之中置為了空指針。

int main()

{

Time test(10,25,12);

Time test2(move(test));

return 0;

}

執(zhí)行結(jié)果:

move

call ~Time()

call ~Time()

通過(guò)這樣的方式來(lái)減少不必要的內(nèi)存操作。但是之后我們也無(wú)法再訪問(wèn)test對(duì)象的內(nèi)容了,因?yàn)槎荚谝苿?dòng)構(gòu)造函數(shù)之中置為了空指針。將亡值通過(guò)移動(dòng)構(gòu)造函數(shù)”借尸還魂“,通過(guò)test2變量延續(xù)了自己的生命周期。

3.左值的一些"坑"

雖然筆者給出了左右值分辨的一些基本標(biāo)準(zhǔn),但是還是有下面一些很讓人迷惑的場(chǎng)景:

條件表達(dá)式返回左值true ? i : i;

++i++ // 左值

++i // 右值

[]數(shù)組取值返回左值i[10]

指針取值操作符返回左值*i

字符串字面量返回左值“hello world”

這是一些表示左值的特殊情況,這里筆者也不展開(kāi)一一贅述了,希望大家可以簡(jiǎn)單的進(jìn)行記憶。當(dāng)然,筆者從來(lái)不去記一些太瑣碎的問(wèn)題,因?yàn)樘麟y記了,所以在C++11之中,可以標(biāo)準(zhǔn)庫(kù)中添加的模板類is_lvalue_reference來(lái)判斷表達(dá)式是否為左值,is_rvalue_reference來(lái)判斷是否為右值。

cout << is_lvalue_reference::value << endl;

cout << is_rvalue_reference::value << endl;

返回1則為真,0為假。

4.小結(jié)

這只是我們對(duì)C++類型系統(tǒng)的第一篇探討,后續(xù)筆者還會(huì)繼續(xù)深入的探討有關(guān)C++11新特性之中與類型系統(tǒng)相關(guān)的內(nèi)容,歡迎大家多多討論,指教。

內(nèi)容來(lái)源于網(wǎng)絡(luò)如有侵權(quán)請(qǐng)私信刪除

總結(jié)

以上是生活随笔為你收集整理的c语言 变量的左值和右值,C++雾中风景10:聊聊左值,纯右值与将亡值的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。