C++賦值函數詳解

來源:互聯網
上載者:User

標籤:使用   ar   時間   amp   new   c++   har   程式   

賦值函數
        每個類只有一個賦值函數  
        由於並非所有的對象都會使用拷貝建構函式和賦值函數,程式員可能對這兩個函數有些輕視。
    1,如果不主動編寫拷貝建構函式和賦值函數,編譯器將以“位拷貝”的方式自動產生預設的函數。倘若類中含有指標變數,那麼這兩個預設的函數就隱含了錯誤。
               以類String的兩個對象a,b為例,假設a.m_data的內容為“hello”,b.m_data的內容為“world”。   
               現將a賦給b,預設賦值函數的“位拷貝”意味著執行b.m_data = a.m_data。
               這將造成三個錯誤:             
                        一是b.m_data原有的記憶體沒被釋放,造成記憶體泄露;
                        二是b.m_data和a.m_data指向同一塊記憶體,a或b任何一方變動都會影響另一方;
                        三是在對象被析構時,m_data被釋放了兩次。   
        2,拷貝建構函式和賦值函數非常容易混淆,常導致錯寫、錯用。拷貝建構函式是在對象被建立時調用的,而賦值函數只能被已經存在了的對象調用。以下程式中,第三個語句和第四個語句很相似,你分得清楚哪個調用了拷貝建構函式,哪個調用了賦值函數嗎?  
           String a(“hello”);   
             String b(“world”); 
             String c = a;   // 調用了拷貝建構函式,最好寫成 c(a); 
          c = b;      // 調用了賦值函數   
               本例中第三個語句的風格較差,宜改寫成String c(a) 以區別於第四個語句。   
        類String的拷貝建構函式與賦值函數   
 // 拷貝建構函式            
         String::String(const String &other)   
         {   
             int length = strlen(other.m_data);  // 允許操作other的私人成員m_data 
               m_data = new char[length+1];  
             strcpy(m_data, other.m_data);  
      }   
// 賦值函數   
      String & String::operator =(const String &other)   
       {  
                if(this == &other)          // (1) 檢查自賦值
                          return *this;   
          delete [] m_data;            // (2) 釋放自己原有的記憶體資源 
              int length = strlen(other.m_data);     // (3)分配新的記憶體資源,並複製內容
            m_data = new char[length+1];   
              strcpy(m_data, other.m_data);   
            
              return *this;              // (4)返回本對象的引用
   }   
      類String拷貝建構函式與普通建構函式的區別是:在函數入口處無需與NULL進行比較,這是因為“引用”不可能是NULL,而“指標”可以為NULL。 
   類String的賦值函數比建構函式複雜得多,分四步實現:   
                (1)第一步,檢查自賦值。你可能會認為多此一舉,難道有人會愚蠢到寫出 a = a 這樣的自指派陳述式!的確不會。但是間接的自賦值仍有可能出現,例如   // 內容自賦值   b = a;   …   c = b;   …   a = c;   // 地址自賦值   b = &a;   …   a = *b;   也許有人會說:“即使出現自賦值,我也可以不理睬,大不了化點時間讓對象複製自己而已,反正不會出錯!”   他真的說錯了。看看第二步的delete,自殺後還能複製自己嗎?所以,如果發現自賦值,應該馬上終止函數。注意不要將檢查自賦值的if語句   if(this == &other)   錯寫成為   if( *this == other)   
               (2)第二步,用delete釋放原有的記憶體資源。如果現在不釋放,以後就沒機會了,將造成記憶體泄露。   
               (3)第三步,分配新的記憶體資源,並複製字串。注意函數strlen返回的是有效字串長度,不包含結束符‘\0’。函數strcpy則連‘\0’一起複製。   
               (4)第四步,返回本對象的引用,目的是為了實現象 a = b = c 這樣的鏈式表達。注意不要將 return *this 錯寫成 return this 。那麼能否寫成return other 呢?效果不是一樣嗎?       不可以!因為我們不知道參數other的生命期。有可能other是個臨時對象,在賦值結束後它馬上消失,那麼return other返回的將是垃圾。   偷懶的辦法處理拷貝建構函式與賦值函數   如果我們實在不想編寫拷貝建構函式和賦值函數,又不允許別人使用編譯器產生的預設函數,怎麼辦?

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.