<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      深度解析C++拷貝構造函數

      自2003年開始,斷斷續續用了12年C++,直到這兩年做物聯網嵌入式開發,感覺對C++的掌握僅有10%左右。
      習慣了C#開發,C++倒顯得難以下手!今天就一個函數返回問題跟輝月兄弟討論一番,大有所獲,足以解決我們目前80%的問題,感覺對C++的掌握上升到了20%。

      背景,現有字節數組ByteArray和字符串String,(不要激動,單片機嵌入式C++很難用起來標準類庫)
      我們需要實現函數String& ByteArray::ToHex()
      其實這是我們在C#上非常常用的函數,把一個字節數組轉為字符串,然后別的地方使用或者顯示出來。C#原型String ToHex(this Byte[] buf)
      這里有一個老大難題:
      1,如果ToHex內部棧分配字符串空間,把字節數組填充進去,那么離開ToHex的時候棧回收,對象數據無效
      2,如果ToHex內部堆分配空間,字節數組填充,離開ToHex的時候得到指針。但是這樣違背了C/C++誰申請誰釋放的原則,其它小伙伴使用ToHex的時候可能忘了釋放
      3,最后只能折中,做成String& ByteArray::ToHex(String& str); 別提多憋屈!最受不了的是,外部分配str的時候,還得考慮數組有多長!這些本來最好由ToHex內部解決的問題。

      總之,這個問題就這樣折騰了我12年!

      知道今天,跟輝月兄弟聊起這個問題,他也有十多年C++歷史,用得比我要多一些。他有一段常用代碼大概如下:

      CString Test()
      {
              CString a = "aaaa";
              CString b = "bbbb";
              CString c = a + b;
      
              return c;
      }

      按他說法,就這樣子寫了十多年!
      我說c不是棧分配嗎?離開的時候會被析構吧,外部怎么可能拿到?他說是哦,從來沒有考慮過這個問題。
      我們敏銳的察覺到,C++一定可以實現類似的做法,因為字符串相加就是最常見的例子。

      經過一番探討,我們發現關鍵點出在拷貝構造函數上面

      測試環境:編譯器Keil MDK 5.14,處理器STM32F407VG

      1、進出兩次拷貝
      做了一個測試代碼,兩次調用拷貝構造函數

      class A
      {
      public:
              char* str;
      
          A(char* s)
          {
                      str = s;
              debug_printf("A %s 0x%08X\r\n", str, this);
          }
              A(const A &a)
              {
              debug_printf("A.Copy %s 0x%08X => %s 0x%08X\r\n", a.str, &a, str, this);
              }
          ~A()
          {
              debug_printf("~A %s 0x%08X\r\n", str, this);
          }
      };
      
      class B : public A
      {
      public:
          B(char* s) : A(s)
          {
              debug_printf("B %s 0x%08X\r\n", str, this);
          }
              B(const B &b) : A(b.str)
              {
              debug_printf("B.Copy %s 0x%08X => %s 0x%08X\r\n", b.str, &b, str, this);
              }
          ~B()
          {
              debug_printf("~B %s 0x%08X\r\n", str, this);
          }
              B& operator=(const B &b)
              {
              debug_printf("B.Assign %s 0x%08X => %s 0x%08X\r\n", b.str, &b, str, this);
                      return *this;
              }
      };
      
      B fun(B c)
      {
              c.str = "c";
          return c;
      }
      
      void CtorTest()
      {
              B a("a"), b("b");
              debug_printf("start \r\n");
          b = fun(a);
              debug_printf("end \r\n");
      }

      執行結果如下:

      A a 0x2001FB78
      B a 0x2001FB78
      A b 0x2001FB74
      B b 0x2001FB74
      start 
      A a 0x2001FB7C
      B.Copy a 0x2001FB78 => a 0x2001FB7C
      A c 0x2001FB80
      B.Copy c 0x2001FB7C => c 0x2001FB80
      B.Assign c 0x2001FB80 => b 0x2001FB74
      ~B c 0x2001FB80
      ~A c 0x2001FB80
      ~B c 0x2001FB7C
      ~A c 0x2001FB7C
      end 
      ~B b 0x2001FB74
      ~A b 0x2001FB74
      ~B a 0x2001FB78
      ~A a 0x2001FB78
      • 進入func的時候,參數進行了一次拷貝,c構造,也就是7C,然后a拷貝給c
      • 離開func的時候,產生了臨時對象80,并把7C拷貝給80
      • func返回值賦值給b,也就是臨時對象80賦值給74
      • 然后才是80和7C的析構。
      • 那么關鍵點就在于這個臨時對象,它的作用域橫跨函數內部和調用者,自然不怕析構回收。
      • 不過奇怪的是,內部參數7C為何在外面析構??



      2、進去拷貝出來引用
      修改func函數,返回引用,少一次拷貝構造

      B& fun(B c)
      {
              c.str = "c";
          return c;
      }

      執行結果如下:

      A a 0x2001FB70
      B a 0x2001FB70
      A b 0x2001FB6C
      B b 0x2001FB6C
      start 
      A a 0x2001FB74
      B.Copy a 0x2001FB70 => a 0x2001FB74
      B.Assign c 0x2001FB74 => b 0x2001FB6C
      ~B c 0x2001FB74
      ~A c 0x2001FB74
      end 
      ~B b 0x2001FB6C
      ~A b 0x2001FB6C
      
      ~A a 0x2001FB70
      • 進去的時候參數來了一次拷貝構造74
      • 出來的時候74直接賦值給6C,也就是b。看樣子,按引用返回直接省去了臨時對象。
      • 但是上面這個代碼編譯會有一個警告,也就是返回本地變量的引用。
      • 賦值以后,內部對象74才被析構
      • 雖然有警告,但是對象還沒有被析構,外面可以使用。按理說每個線程都有自己的棧,不至于那么快被別的線程篡改數據。但是很難說硬件中斷函數會不會用到那一塊內存。
      • 這里有個非常奇怪的現象,沒有見到70的B析構,不知道是不是串口輸出信息太快,丟失了這一部分數據,嘗試了幾次都是如此。


      3、引用進去引用出來
      修改參數傳入引用,再少一次拷貝構造

      B& fun(B& c)
      {
              c.str = "c";
          return c;
      }

      執行結果如下:

      A a 0x2001FB88
      B a 0x2001FB88
      A b 0x2001FB84
      B b 0x2001FB84
      start 
      B.Assign c 0x2001FB88 => b 0x2001FB84
      end 
      ~B b 0x2001FB84
      ~A b 0x2001FB84
      ~B c 0x2001FB88
      ~A c 0x2001FB88
      • 更加徹底,沒有任何拷貝構造函數被執行
      • 并且沒有“返回本地變量引用”的警告


      End

      posted @ 2017-09-01 22:56  大石頭  閱讀(1851)  評論(15)    收藏  舉報
      主站蜘蛛池模板: а∨天堂一区中文字幕 | 国产尤物精品自在拍视频首页| 中文字幕国产精品专区| 无码AV无码免费一区二区| 曝光无码有码视频专区| 精品国产福利一区二区在线| 日韩中文字幕精品人妻| 国产三级精品三级在线区| 小雪被老外黑人撑破了视频| 又爽又黄又无遮掩的免费视频| 美国又粗又长久久性黄大片| 在线看国产精品自拍内射| 国产成年女人特黄特色大片免费| 94人妻少妇偷人精品| 国产做a爱片久久毛片a片| A级毛片100部免费看| 无码一区二区波多野结衣播放搜索| 色欲综合久久中文字幕网| 精品熟女少妇免费久久| 日韩久久久久久中文人妻| 人妻精品动漫h无码| 国内精品一区二区不卡| 精品综合久久久久久97| 377p日本欧洲亚洲大胆张筱雨| 性色欲情网站iwww九文堂| 久久久久无码中| 麻豆精品久久精品色综合| jizzjizz日本高潮喷水| 欧美丰满熟妇xxxx性| 久久久久成人精品无码中文字幕| 国产精品久久久久久免费软件| 亚洲高潮喷水无码AV电影| 日韩精品人妻系列无码av东京| 亚洲一区二区三区在线观看精品中文 | 国产精品普通话国语对白露脸| 亚洲AV成人片在线观看 | 国产盗摄xxxx视频xxxx| 亚洲精品视频一二三四区| 免费人成网站免费看视频| 天堂中文8资源在线8| 极品无码国模国产在线观看|