国产精品天干天干,亚洲毛片在线,日韩gay小鲜肉啪啪18禁,女同Gay自慰喷水

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

深入淺出C++:完美轉(zhuǎn)發(fā)不完美

2022-06-08 12:08 作者:飛翔の回聲_FlappyEcho  | 我要投稿

????上一次文章里,我在梳理了以std::move為基礎(chǔ)的移動語義的場景和概念。

深入淺出C++:移動語義不移動 - 嗶哩嗶哩 (bilibili.com)

????在這一個專欄里,我將探討完美轉(zhuǎn)發(fā),在加入了針對完美轉(zhuǎn)發(fā)的敘述以后,理論和概念層面針對C++11移動語義的討論就可以基本結(jié)束了。

????我仍然會結(jié)論先行:

????所謂完美轉(zhuǎn)發(fā),其實只是根據(jù)【不同的情況】傳遞左值引用或者右值引用兩種情況以精準調(diào)用相應(yīng)的函數(shù)重載。而所謂【不同的情況】,則根據(jù)std::forward<T>的模板參數(shù)T來決定,可以簡單的認為,在考慮引用折疊的情況下,當(dāng)T推導(dǎo)出來的類型帶有奇數(shù)個&時,轉(zhuǎn)發(fā)左值引用,偶數(shù)個(包括0)時轉(zhuǎn)發(fā)右值引用。

????好了,結(jié)論說完了,如果有些同學(xué)可以理解我所說的結(jié)論,并且表示大大的認可,你們就已經(jīng)可以退出這篇文章去尋找對自己更有意義的內(nèi)容去了。

????而那些抱有不同觀念的人以及并不能理解的同學(xué)們,則可以開始閱讀我接下來的說法,或是嘗試去理解,或是去思考與我辯論的說辭,我十分歡迎有同學(xué)愿意以私信或者評論的方式與我討論這些內(nèi)容。

????在上次針對std::move的討論中,我將左值與右值的基礎(chǔ)概念扔給了cppreference,我可以接受你們對使用std::move和std::forward存在疑惑,但我確實需要你們具備識別左值和右值的能力。

? ? 最基本的。

????在上述的代碼中,我需要你能知道,因為test是一個左值,所以第一個Test的調(diào)用回事參數(shù)為const Data&的版本,而Data(12)并沒有一個擁有名字的變量來接住它,它的生命周期僅在這一行代碼,故而它是一個右值,因此會調(diào)用到Data &&的Test重載版本。

????在各位能區(qū)分左值和右值的情況下,我們繼續(xù)。

????我相信各位能夠通過各種途徑來查到std::move和std::forward的源碼,亦或是相近的實現(xiàn),我在這里隨便貼出來一個。

????C++標準庫的很多工具的實現(xiàn),真的是體現(xiàn)了一個大道至簡的真理。包括std::enable_if也一樣,這些在應(yīng)用中能解決開發(fā)者很多問題的東西,實現(xiàn)起來確實相當(dāng)?shù)暮唵?。甚至在你使用enable_if的時候,你自己需要往模板里塞的東西要比enable_if自己的實現(xiàn)還要多。

????當(dāng)然上述的話屬于是閑聊,這段代碼理解起來不難(額,好吧,哪怕寫的挺短但看上去還是挺不符合平日里應(yīng)用程序的編碼的,但那不重要),我也并不打算講這段代碼,而你只需要關(guān)注到那個static_cast就足夠了。這個東西是什么?就是一個類型轉(zhuǎn)換而已。

????想想咱們寫的兩篇文章的名字,移動語義不移動,完美轉(zhuǎn)發(fā)不完美。

? ? 這足以說明:std::move和std::forward就是兩個【能夠根據(jù)不同情況】而進行的【強制類型轉(zhuǎn)換】,為的就是我先行結(jié)論中的精準調(diào)用相應(yīng)的函數(shù)重載。

????功能上,std::forward甚至能夠完美取代std::move,只要你不怕多打那近乎一倍的字,雖然從標準庫的作者角度上來說,他們就是希望我們針對兩種不同的語境來使用這兩個不同的工具。

????如此看來:

????std::move能夠?qū)⑷魏涡问降囊靡杂抑狄梅祷兀?br>????std::forward能夠?qū)⑷魏涡问降囊靡云湓镜囊眯问椒祷兀ㄖ荒芟薅樽笾狄没蛘哂抑狄茫?/span>

????我們知道,函數(shù)傳參有3中形式,按引用,按值和按指針。假如你能夠深刻的理解所謂【指針也是一個變量】的話,就會明白,按值傳遞和按指針傳遞的本質(zhì)是一樣的。通過上述總結(jié),咱們應(yīng)該清楚,完美轉(zhuǎn)發(fā)是不能夠按值轉(zhuǎn)發(fā)的,這是其不完美的其中之一。

????考慮如下代碼:

????如上的代碼使用g++編譯器編譯運行后,結(jié)果如圖:

代碼運行結(jié)果

????我將運行結(jié)果對應(yīng)注釋在了函數(shù)邊上。

????而且我們可以看到,最終調(diào)用的是形參為Data &的函數(shù)而非const Data&,對于并非const Data類型的對象test而言,這無可厚非。

????而我如果將這個地方展開來說,就會涉及一些關(guān)于模板的坑,這個坑可以用一句話來總結(jié)就是:因為重載決議的緣故,導(dǎo)致你想要調(diào)用的【可調(diào)用對象】和編譯器實際調(diào)用的【可調(diào)用對象】不一樣。

????其中,對于函數(shù)形參的類型有沒有const等關(guān)鍵字來修飾,會是重載決議考慮的范疇。

????而針對這個知識點,Effective Modern C++ 的條款26和27有非常詳細的展開,讓我來簡述肯定是不如專家解釋的靠譜的。

????針對這段代碼,我們可以知道,std::move無論怎么折騰,只會返回右值引用,std::forward則會根據(jù)傳給它的模板參數(shù)不同而根據(jù)不同情況返回左值引用或右值引用,無論怎么說,它們返回的都是引用,絕對不是值。

????你不能夠干出寫一個值傳遞的函數(shù),然后接收一個std::forward轉(zhuǎn)發(fā)的對象就說它能夠傳遞值,那只是函數(shù)的形參以實參作為【引用參數(shù)】進行了一個拷貝。

????我們明確了完美轉(zhuǎn)發(fā)只會轉(zhuǎn)發(fā)引用后,再考慮現(xiàn)實的應(yīng)用場景,可以總結(jié)出:當(dāng)我們使用完美轉(zhuǎn)發(fā)的時候,幾乎都是配合著模板和萬能引用來使用的。

????原因是:萬能引用會讓形參最終都會被推導(dǎo)為引用類型的數(shù)據(jù),而模板則需要供std::forward來根據(jù)類型進行精準的引用轉(zhuǎn)發(fā)使用。

????看一個簡單的代碼,它還是我從Effective Modern C++上抄來的。

?????配合著T&&,param這個形參無論如何都會被編譯器推導(dǎo)為引用,這個時候你需要考慮引用折疊。

????在logAndProcess(w);這段代碼里,w是左值,param則被推導(dǎo)為Widget&,則表明,Widget& 與 T&&是等價的。這個時候,T就會根據(jù)引用折疊被推導(dǎo)為Widget&類型。
? ? (當(dāng)T為Widget&時,T&&對應(yīng)Widget&&&,引用折疊可以消去【2的倍數(shù)個&符號】,直到【類型最后后面的&符號數(shù)量】 <= 2,故Widget&&&可以消去兩個&,轉(zhuǎn)成Widget&型與w的類型相匹配。)

????如果還不懂,我們再看logAndProcess(std::move(w));這段代碼,param對應(yīng)的必然是一個Widget&&,則T&&與Widget&&等價,還用我說T是什么類型嗎?T會被推導(dǎo)為Widget類型。

????而std::forward<Widget>(param)和std::forward<Widget&>(param)會出現(xiàn)什么結(jié)果早在之前的代碼演示中我們就給出了答案,還記得我們先行的結(jié)論嗎:

????可以簡單的認為,在考慮引用折疊的情況下,當(dāng)T推導(dǎo)出來的類型帶有奇數(shù)個&時,std::forward轉(zhuǎn)發(fā)左值引用,偶數(shù)個(包括0)時,std::forward轉(zhuǎn)發(fā)右值引用。

????這個簡單但是神奇模板應(yīng)用最終讓std::forward根據(jù)模板參數(shù)T的類型轉(zhuǎn)發(fā)相應(yīng)的引用,而結(jié)果上與形參param的類型結(jié)果完美匹配。

????還記的本文叫什么嗎?完美轉(zhuǎn)發(fā)不完美。并不完美的完美轉(zhuǎn)發(fā)其實還有其他不完美的地方,在某些奇怪的場景下,它會類型推導(dǎo)錯誤進而導(dǎo)致執(zhí)行失敗,而這一點在Effective Modern C++的條款30也有十分詳細的說明,才疏學(xué)淺且并沒有為此準備的我就不在本文展開了。

????而我要表達的核心內(nèi)容,到此為止就算是全部結(jié)束了。

????考慮到我對于移動語義大部分的理解和思考已經(jīng)在上一篇文章中全部表達了,配合著std::forward的此文僅僅是將移動語義的基礎(chǔ)知識面說全了而已,因此本文的內(nèi)容并不像之前那么多。

????如果您覺得我寫的文章對您有幫助亦或是想與我交流,都歡迎您在評論區(qū)留言。如果您對其他的知識點或是語言特性感興趣,也可以嘗試著讓我知道,若是我自己達到了能夠分享該知識點的水平,便會想辦法在日后繼續(xù)寫相關(guān)文章。

????最后,十分感謝您的閱讀,我們有緣再見。

????


深入淺出C++:完美轉(zhuǎn)發(fā)不完美的評論 (共 條)

分享到微博請遵守國家法律
武隆县| 永和县| 通州市| 繁峙县| 瑞金市| 盱眙县| 交口县| 屏东市| 铜川市| 岑巩县| 福贡县| 正定县| 和政县| 贞丰县| 平远县| 克东县| 合水县| 合江县| 高尔夫| 申扎县| 嘉鱼县| 克山县| 泗水县| 财经| 会理县| 漯河市| 固安县| 绥江县| 崇阳县| 琼海市| 冀州市| 包头市| 杭锦后旗| 琼中| 来凤县| 昭苏县| 广德县| 蓬溪县| 平谷区| 临泉县| 保靖县|