C++有關拷貝構造函數(默認/淺/深拷貝構造函數)


拷貝結構函數顧名思義就是復制對象。

先講一下默認拷貝函數:

默認拷貝就是直接賦值,讓程序調用默認拷貝結構函數。

Student p1;

Student p2 = p1//或者Student p2(p1);

 

程序開始運行時,創建p1對象,p1對象的構造函數從堆中分配空間並賦給數據成員pName,執行,p2=p1時,因為沒有定義拷貝構造函數,於是就調用默認拷貝構造函數,
 
使得p2與p1完全一樣,並沒有新分配堆空間給p2,  p1與p2的pName都是同一個值。析構p2時,將堆中字符串清成空串,然后將堆空間返還給系統;
 
析構p1時,因為這是pName指向的是空串,所以第三行輸出中顯示的只是Destructing,當執行 delete pName ; 按道理系統應該報錯,但在gcc中沒有。

 

重點講一下,深拷貝和淺拷貝。

這里借鑒一個前輩的例子:(前輩寫的很好,大家可以看下)

https://www.cnblogs.com/raichen/p/4752025.html

#include <iostream>
#include <cstring>
class Person 
{
public :
         
    // 構造函數
    Person(char * pN)
    {
        cout << "一般構造函數被調用 !\n";
        m_pName = new char[strlen(pN) + 1];
        //在堆中開辟一個內存塊存放pN所指的字符串
        if(m_pName != NULL) 
        {
           //如果m_pName不是空指針,則把形參指針pN所指的字符串復制給它
             strcpy(m_pName ,pN);
        }
    }        
       
    // 系統創建的默認復制構造函數,只做位模式拷貝
    Person(Person & p)    
    { 
        //使兩個字符串指針指向同一地址位置         
        m_pName = p.m_pName;         
    }
 
    ~Person( )
    {
        delete m_pName;
    }
         
private :
    char * m_pName;
};
 
void main( )
{ 
    Person man("lujun");
    Person woman(man); 
     
    // 結果導致   man 和    woman 的指針都指向了同一個地址
     
    // 函數結束析構時
    // 同一個地址被delete兩次
}
 
 
// 下面自己設計復制構造函數,實現“深拷貝”,即不讓指針指向同一地址,而是重新申請一塊內存給新的對象的指針數據成員
Person(Person & chs);
{
     // 用運算符new為新對象的指針數據成員分配空間
     m_pName=new char[strlen(p.m_pName)+ 1];
 
     if(m_pName)         
     {
             // 復制內容
            strcpy(m_pName ,chs.m_pName);
     }
   
    // 則新創建的對象的m_pName與原對象chs的m_pName不再指向同一地址了
}

因為編譯不同,可能不能通過編譯,但這不是重點。

 

直接利用淺拷貝,m_pName = p.m_pName,后者復制給前者,但資源(堆空間)並未復制給前者,相當於這兩個都同時指向同一地址,造成或釋放兩次內存。

深拷貝上面例子可以看到,會給它新申請一個空間。

注意:(引用)“如果需要析構函數,則一定需要拷貝構造函數和賦值操作符。

 

什么情況使用復制構造函數:

類的對象需要拷貝時,拷貝構造函數將會被調用。以下情況都會調用拷貝構造函數:


(1)一個對象以值傳遞的方式傳入函數體 


(2)一個對象以值傳遞的方式從函數返回 


(3)一個對象需要通過另外一個對象進行初始化。

同時別人推薦的讀的文章:https://blog.csdn.net/fdsafwagdagadg6576/article/details/51723823

 

想要了解跟多可以了解一下這篇文章:《面向對象進價--拷貝構造函數》

然后可以看下例子:多繼承的例子(附詳解)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM