免费爱碰视频在线观看,九九精品国产屋,欧美亚洲尤物久久精品,1024在线观看视频亚洲

      聊聊 C++ 右值引用 和 移動構造函數(shù)

      聊聊 C++ 右值引用 和 移動構造函數(shù)

      一: 背景

      最近在看 C++ 的右值引用和移動構造函數(shù),感覺這東西一時半會還挺難理解的,可能是沒踩過這方面的坑,所以沒有那么大的深有體會,不管怎么說,這一篇我試著聊一下。

      二: 右值引用

      1. 它到底解決了什么問題?

      在其他編程語言中,很少聽到 右值引用 這個詞,我個人感覺還是 C++ 這個 值類型 優(yōu)先的語言基因決定的,我們都知道 值類型 作為方法參數(shù)或者返回值時會生成自身的副本,如果 值類型 很大,那一來一回生成若干個深復制的 臨時對象 將會產(chǎn)生巨大的性能開銷。

      總結(jié)一句話:右值引用 就是盡可能的減少這中間 臨時對象 個數(shù),尤其是關聯(lián)到 heap 上的對象,僅此而已。

      2. 右值引用是個什么樣子?

      說到 右值引用 得先說什么是 右值,左值 , 左值 一般都是帶有內(nèi)存地址變量,而 右值 一般是立即數(shù)或者運算過程中的臨時對象,這種對象不會有地址值,是不是很繞,我舉個例子吧。

      int main(){int i = 10;int j = 11;int sum = i + j;}

    1. 10,11,(i+j)
    2. 屬于右值,因為它本身沒有內(nèi)存地址,除非把它們放入到棧中或者堆中。

    3. i,j,sum
    4. 屬于左值,因為它們是線程棧上地址的標識符。

      知道了 左右值 概念,接下來理解 左右值引用 就很簡單了,既然是 引用,必然是多個變量指向同一個地址,對吧,修改下代碼如下:

      int main(){int i = 10;int& k = i;//左值引用int&& m = 10;//右值引用}

      接下來看下匯編代碼:

      33: int i = 10;00FB182F mov dword ptr [ebp-0Ch],0Ah 34: int& k = i;00FB182F mov dword ptr [ebp-0Ch],0Ah 00FB1836 lea eax,[ebp-0Ch] 00FB1839 mov dword ptr [ebp-18h],eax 36: int&& m = 10;00FB183C mov dword ptr [ebp-30h],0Ah 00FB1843 lea eax,[ebp-30h] 00FB1846 mov dword ptr [ebp-24h],eax

      從匯編代碼看,它們是一模一樣的,也就是說在匯編層面,其實并沒有 右值引用 和 左值引用 一說。

      有了這些基礎,我們來看下更復雜的 class 結(jié)構。

      三: 右值引用如何減少對象的創(chuàng)建

      1. 簡要思路

      其實仔細想一想,減少臨時對象的創(chuàng)建,無非就是在運算過程中復用一些對象,不需要每次都走賦值構造函數(shù)來進行深復制,畫個圖就像下面這樣。

      明白了這個思路,接下來我們舉一個例子說明。

      2. 一個簡單的例子

      C++ 最煩的地方就是有太多的構造函數(shù), 數(shù)不勝數(shù),太尷尬了,這里我做一個簡單的 + 操作例子。

      #include #include using namespace std;class StringBuidler {public:char* str;int length;public:StringBuidler() {}StringBuidler(int len, char c) {this->str = new char[len];this->str[0] = c;this->length = len;}StringBuidler(const StringBuidler& s) {printf(“StringBuidler:深復制 “);this->length = s.length;this->str = new char[s.length];for (size_t i = 0; i str[i] = s.str[i];}}StringBuidler operator+(const StringBuidler& p) {StringBuidler tmp;tmp.length = this->length + p.length;tmp.str = new char[tmp.length];int index = 0;for (size_t i = 0; i length; i++){tmp.str[index++] = this->str[i];}for (size_t i = 0; i < p.length; i++){tmp.str[index++] = p.str[i];}return tmp;}};int main(){StringBuidler s1(10, 'a');StringBuidler s2(5, 'b');StringBuidler s3 = s1 + s2;printf("s3.length=%d, s1.length=%d, s2.length=%d ", s3.length, s1.length, s2.length);}折疊

      從這個例子中可以看到,s1+s2 操作中出現(xiàn)了一次 深copy,具體代碼出現(xiàn)在 return 處,匯編代碼如下:

      因為是深復制,所以會再次生成一個 new char[] ,如果 new char[] 很大,那將會是不必要的性能開銷,能不能像我畫的圖一樣,將 s3 中的 str 指針直接指向 tmp 所持有的 heap 上的 char[] 數(shù)組來達到復用目的呢? 肯定是可以的。

      3. 性能優(yōu)化方案

      這里需要用 右值引用 + 移動構造函數(shù) 讓 s3.str 指向 tmp.str,從而避免復制構造函數(shù),在 StringBuilder 類中加一個方法如下:

      StringBuidler(StringBuidler&& s) {this->str = s.str;this->length = s.length;s.str = nullptr;}

      然后把程序跑起來,截圖如下:

      可以看到,深復制已經(jīng)沒有了,這個過程會在 return 處被調(diào)用,編譯器會判斷如果是右值的話,自動走 移動構造函數(shù),沒有這個函數(shù)就會走 賦值構造函數(shù)。

      四: 總結(jié)

      總之 右值引用 可以讓你盡可能的復用一些中間對象,達到一個性能上的提升,其實對 C# 程序員來說,這么簡單的引用賦值,C++ 搞出了這么多概念,真的很難理解,可能還是那句話,這是 C++ 的值類型優(yōu)先的基因決定的。

      鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權歸原作者所有,如有侵權請聯(lián)系管理員(admin#wlmqw.com)刪除。
      (0)
      用戶投稿
      上一篇 2022年7月26日 15:14
      下一篇 2022年7月26日 15:14

      相關推薦

      • 適合發(fā)朋友圈有個性走心的文案

        1、保持炙熱,堅持下去。因為喜歡,可迎萬難。好好生活,慢慢相遇。2、也許你想要的未來 在別人眼里不值一提 也許你已經(jīng)很努力了 可還是有人不滿意 但請你繼續(xù)向前走 因為別人看不到你的…

        2022年8月18日
      • Django REST framework學習筆記(3)-請求和響應

        Django REST framework在Django原有的基礎上,新增了一個request對象繼承了APIView視圖類,并在原有的HttpResponse響應類的基礎上實現(xiàn)了…

        2022年7月4日
      • 對話框管理器第三章:創(chuàng)建控件

        和上一篇創(chuàng)建框架窗口相比,創(chuàng)建控件的工作要輕松很多,信不信由你。在對話框模板中定義的每一個控件,其對應的子窗口將會被創(chuàng)建。控件的大小和位置在模板中是以DLU為單位來描述的,所以,理…

        2022年7月28日
      • 雙十一首次支持多地址合并下單設置方法(雙十一首次支持多地址合并下單)

        雙十一馬上就要到了,不少小伙伴已經(jīng)開始加購自己想要的商品了。有網(wǎng)友發(fā)現(xiàn)淘寶平臺悄悄上線了多地址下單功能,支持給不同的商品添加不同的地址,給家人朋友送的心意可以在同一個訂單里一起享受…

        2022年10月19日
      • 前端JavaScript – 關于CJS,AMD,UMD,ESM,看這里一次性搞懂

        看了不少關于這個話題的文章,很多都說不清楚,老是Get不到重點。下面就把他們總結(jié)一下,讓大家不再疑惑。 開始的時候,JavaScript沒有import/export 模塊的方法。…

        2022年6月20日
      • 普通人也能活到120歲?哈佛醫(yī)學院這3種方法值得一試

        如果說有一件事情是人類發(fā)展以來沒有停止探索的,那我想“延長壽命”一定榜上有名! 古有歷朝皇帝“尋仙山”、“服靈藥”、追求長生不老,今有買靈芝、熬人參、吃阿膠的人們,但愿延年益壽。大…

        2022年9月10日
      • 736. Lisp 語法解析 : DFS 模擬題

        題目描述 這是 LeetCode 上的 736. Lisp 語法解析 ,難度為 困難。 Tag : 「DFS」、「模擬」、「哈希表」 給你一個類似 Lisp 語句的字符串表達式 e…

        2022年7月8日
      • 如何利用wrap測試oss性能?

        前言 我們利用mino與ceph rgw搭建好的oss經(jīng)過多層網(wǎng)絡轉(zhuǎn)發(fā),傳輸速度必定有所折損,這個時候我們使用wrap來測試oss對象存儲的真實性能。 利用wrap測試oss性能 …

        2022年6月18日
      • 100+經(jīng)典Java面試題及答案解析

        面向?qū)ο缶幊蹋∣OP) Java是一個支持并發(fā)、基于類和面向?qū)ο蟮挠嬎銠C編程語言。下面列出了面向?qū)ο筌浖_發(fā)的優(yōu)點: 代碼開發(fā)模塊化,更易維護和修改。 代碼復用。 增強代碼的可靠性…

        2022年8月5日
      • Surge IOS (windows客戶端)配置

        相信很多朋友都有聽過這款神器的名字,這是一款功能強大且非常好用的應用,用戶可以用來阻擋廣告、網(wǎng)絡調(diào)試、流量跟蹤、代理上網(wǎng)等,雖然特別實用,但是該軟件的使用還是有許多需要注意的地方,…

        2022年6月17日

      聯(lián)系我們

      聯(lián)系郵箱:admin#wlmqw.com
      工作時間:周一至周五,10:30-18:30,節(jié)假日休息