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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Cpp / 右值、纯右值、将亡值

發(fā)布時(shí)間:2024/10/14 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Cpp / 右值、纯右值、将亡值 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、左值與右值

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

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

int x; int y;x = 1; y = 2; x = y; y = x;// 以下代碼有誤 3 = x; x + y = 4;

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

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

二、將亡值

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

glvalue(泛左值) = lvalue (傳統(tǒng)意義上的左值)+ xvalue(消亡值,通過右值引用產(chǎn)生)

rvalue (傳統(tǒng)意義上的右值) = prvalue(純右值) + xvalue

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

  • 返回右值引用的函數(shù)的調(diào)用表達(dá)式。
  • 轉(zhuǎn)換為右值引用的轉(zhuǎn)換函數(shù)的調(diào)用表達(dá)式。

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

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

#include <iostream>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){std::cout << "copy contruct." << std::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;std::cout << "move contruct." << std::endl;}~Time(){std::cout << "call ~Time()" << std::endl;delete hour;delete minute;delete second;} };

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

int main() {Time test(10,25,12);Time test2(test);return 0; }

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

copy contruct. call ~Time() call ~Time()

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

int main() {Time test(10,25,12);Time test2(std::move(test));return 0; }

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

move contruct. call ~Time() call ~Time()

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

三、拓展

1、std::move 的作用是無論你傳給它的是左值還是右值,通過 std::move 之后都變成了右值。

2、++i 是左值,i++ 是右值。

前者,對(duì) i + 1 后再賦給 i,最終的返回值就是 i,所以,++i 的結(jié)果是具名的,名字就是 i;而對(duì)于 i++ 而言,是先對(duì) i 進(jìn)行一次拷貝,將得到的副本作為返回結(jié)果,然后再對(duì) i + 1,由于 i++ 的結(jié)果是對(duì) i + 1前 i 的一份拷貝,所以它是不具名的。假設(shè)自增前i的值是 6,那么,++i 得到的結(jié)果是 7,這個(gè) 7 有個(gè)名字,就是 i ;而 i++ 得到的結(jié)果是 6,這個(gè) 6 是 i + 1 前的一個(gè)副本,它沒有名字,i 不是它的名字,i 的值此時(shí)也是 7。可見,++i 和 i++ 都達(dá)到了使 i + 1的目的,但兩個(gè)表達(dá)式的結(jié)果不同。

?

轉(zhuǎn)自:https://www.cnblogs.com/happenlee/p/9337776.html

(SAW:Game Over!)

總結(jié)

以上是生活随笔為你收集整理的Cpp / 右值、纯右值、将亡值的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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