當前位置:
首頁 > 知識 > 深度解析C++拷貝構造函數

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


背景

現有位元組數組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內部解決的問題。

一段常用代碼大概如下:

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

我說c不是棧分配嗎?離開的時候會被析構吧,外部怎麼可能拿到?他說是哦,從來沒有考慮過這個問題。

我們敏銳的察覺到,C++一定可以實現類似的做法,因為字元串相加就是最常見的例子。

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

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

1、進出兩次拷貝

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

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

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

執行結果如下:

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

  • 進入func的時候,參數進行了一次拷貝,c構造,也就是7C,然後a拷貝給c

  • 離開func的時候,產生了臨時對象80,並把7C拷貝給80

  • func返回值賦值給b,也就是臨時對象80賦值給74

  • 然後才是80和7C的析構。

  • 那麼關鍵點就在於這個臨時對象,它的作用域橫跨函數內部和調用者,自然不怕析構回收。

  • 不過奇怪的是,內部參數7C為何在外面析構??

2、進去拷貝出來引用

修改func函數,返回引用,少一次拷貝構造

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

執行結果如下:

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

  • 進去的時候參數來了一次拷貝構造74

  • 出來的時候74直接賦值給6C,也就是b。看樣子,按引用返回直接省去了臨時對象。

  • 但是上面這個代碼編譯會有一個警告,也就是返回本地變數的引用。

  • 賦值以後,內部對象74才被析構

  • 雖然有警告,但是對象還沒有被析構,外面可以使用。按理說每個線程都有自己的棧,不至於那麼快被別的線程篡改數據。但是很難說硬體中斷函數會不會用到那一塊內存。

  • 這裡有個非常奇怪的現象,沒有見到70的B析構,不知道是不是串口輸出信息太快,丟失了這一部分數據,嘗試了幾次都是如此。

3、引用進去引用出來

修改參數傳入引用,再少一次拷貝構造

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

執行結果如下:

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

  • 更加徹底,沒有任何拷貝構造函數被執行

  • 並且沒有「返回本地變數引用」的警告

文章摘自博客園


中公優就業IT培訓,總有你想學的:http://xue.ujiuye.com

勤工儉學計劃,0元學IT!

http://www.ujiuye.com/zt/qgjx/?wt.bd=lsh11tt

找工作太難?我們來幫你一舉拿下!

http://www.ujiuye.com/zt/jycj/?wt.bd=lsh11tt

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 IT優就業 的精彩文章:

設計模式——裝飾者模式
四季之後,我能記住的,只有你的名字
心理測試|直覺哪根最辣?解析你潛藏的個性!

TAG:IT優就業 |