深度解析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++一定可以實現類似的做法,因為字元串相加就是最常見的例子。
經過一番探討,我們發現關鍵點出在拷貝構造函數上面
測試環境:編譯器Keil MDK 5.14,處理器STM32F407VG
1、進出兩次拷貝
做了一個測試代碼,兩次調用拷貝構造函數
執行結果如下:
進入func的時候,參數進行了一次拷貝,c構造,也就是7C,然後a拷貝給c
離開func的時候,產生了臨時對象80,並把7C拷貝給80
func返回值賦值給b,也就是臨時對象80賦值給74
然後才是80和7C的析構。
那麼關鍵點就在於這個臨時對象,它的作用域橫跨函數內部和調用者,自然不怕析構回收。
不過奇怪的是,內部參數7C為何在外面析構??
2、進去拷貝出來引用
修改func函數,返回引用,少一次拷貝構造
執行結果如下:
進去的時候參數來了一次拷貝構造74
出來的時候74直接賦值給6C,也就是b。看樣子,按引用返回直接省去了臨時對象。
但是上面這個代碼編譯會有一個警告,也就是返回本地變數的引用。
賦值以後,內部對象74才被析構
雖然有警告,但是對象還沒有被析構,外面可以使用。按理說每個線程都有自己的棧,不至於那麼快被別的線程篡改數據。但是很難說硬體中斷函數會不會用到那一塊內存。
這裡有個非常奇怪的現象,沒有見到70的B析構,不知道是不是串口輸出信息太快,丟失了這一部分數據,嘗試了幾次都是如此。
3、引用進去引用出來
修改參數傳入引用,再少一次拷貝構造
執行結果如下:
更加徹底,沒有任何拷貝構造函數被執行
並且沒有「返回本地變數引用」的警告
文章摘自博客園
中公優就業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
![](https://pic.pimg.tw/zzuyanan/1488615166-1259157397.png)
![](https://pic.pimg.tw/zzuyanan/1482887990-2595557020.jpg)
※設計模式——裝飾者模式
※四季之後,我能記住的,只有你的名字
※心理測試|直覺哪根最辣?解析你潛藏的個性!
TAG:IT優就業 |