用彙編的眼光看C++(之算術符重載陷阱)23

來源:互聯網
上載者:User

【 聲明:著作權,歡迎轉載,請勿用於商業用途。  聯絡信箱:feixiaoxing @163.com】

 

    在算術符重載裡面,“=”重載可能是最經常使用的一種。但是好多人就誤以為在函數中,凡是類出現“=”的地方,那就是調用算術符重載,其實不然。為什麼呢?我們可以看看下面的代碼。首先,我們定義一個基本類:

[cpp] view plaincopy
  1. class data  
  2. {  
  3.     char* value;  
  4.     int number;  
  5. public:  
  6.     explicit data(int num = 0){  
  7.         if(num){  
  8.             number = num;  
  9.             value = (char*)malloc(num);  
  10.         }  
  11.     }  
  12.   
  13.     data(const data& d){  
  14.         number = d.get_number();  
  15.         value = (char*)malloc(d.get_number());  
  16.         memmove(value, d.get_point(), d.get_number());  
  17.     }  
  18.   
  19.     ~data(){  
  20.         if(number)  
  21.             free(value);  
  22.     }  
  23.   
  24.     data& operator=(const data& d){  
  25.         if(number)  
  26.             free(value);  
  27.         number = d.get_number();  
  28.         value = (char*)malloc(d.get_number());  
  29.         memmove(value, d.get_point(), d.get_number());  
  30.         return *this;  
  31.       
  32.     }  
  33.   
  34.     int get_number() const {return number;}  
  35.     char* get_point() const {return value;}  
  36. };  

    定義好了函數之後,我們就開始對這個類進行調用,同樣代碼如下所示:

[cpp] view plaincopy
  1. 45:       data m(10);  
  2. 0040108D   push        0Ah  
  3. 0040108F   lea         ecx,[ebp-14h]  
  4. 00401092   call        @ILT+30(data::data) (00401023)  
  5. 00401097   mov         dword ptr [ebp-4],0  
  6. 46:       data p = m;  
  7. 0040109E   lea         eax,[ebp-14h]  
  8. 004010A1   push        eax  
  9. 004010A2   lea         ecx,[ebp-1Ch]  
  10. 004010A5   call        @ILT+35(data::data) (00401028)  
  11. 004010AA   mov         byte ptr [ebp-4],1  
  12. 47:       p = m;  
  13. 004010AE   lea         ecx,[ebp-14h]  
  14. 004010B1   push        ecx  
  15. 004010B2   lea         ecx,[ebp-1Ch]  
  16. 004010B5   call        @ILT+5(data::operator=) (0040100a)  
  17. 48:   }  

    上面共有三句話,我們逐一進行分析:

    45句:定義了一個臨時變數,調用data的建構函式

    46句:出現了一個臨時變數p,這裡發現data類並沒有調用算術符重載函數,而是調用了data的建構函式,根據45句所示,調用的肯定不是普通的建構函式,那麼剩下的結果只能是拷貝建構函式

    47句: 和46句的代碼是一致的,但是此時調用的函數才是算術符重載函數

    所以說,出現“=”的地方未必調用的都是算術符重載函數,也有可能是拷貝建構函式。那麼什麼時候是拷貝建構函式,什麼時候是算術符重載函數呢?判斷的標準 其實很簡單。如果臨時變數是第一次出現,那麼調用的只能是拷貝建構函式,反之如果變數已經存在,就像47句一樣,那麼調用的只能是算術符重載函數,但是我 們這裡定義的算數符重載函數有一個陷阱,不知道大家看出來沒有?

    我提示大家一下,這裡的算術符重載需不需要判斷拷貝的是不是自己呢?

[cpp] view plaincopy
  1. void process()  
  2. {  
  3.     data m(10);  
  4.     data p = m;  
  5.     p = p;  
  6. }  

    這裡最後一句,如果算術符可以自己拷貝給自己,代碼正常編譯和運行都沒有問題,但是在某些情況下會出現很多意想不到的情況。大家可以跟著我的思路來:

[cpp] view plaincopy
  1. data& operator=(const data& d){  
  2.     if(this == &d)       /* check whether it is self-copy action */  
  3.         return *this;  
  4.   
  5.     if(number)  
  6.         free(value);  
  7.     number = d.get_number();  
  8.     value = (char*)malloc(d.get_number());  
  9.     memmove(value, d.get_point(), d.get_number());  
  10.     return *this;  
  11.   
  12. }  

    如果上面的代碼沒有判斷複製的對象是不是自己,那麼我們發現實際上value的資料實際上已經free掉了。那麼此時重新分配記憶體,拷貝的資料只有天知道是什麼資料。原來value指向的記憶體空間就存在了很大的不確定性,這就是算術符重載的陷阱。

 

【後記: 自此用彙編看C++系列全部結束,下面我們將開始資料結構和演算法的討論,歡迎關注】

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.