c++深拷貝和淺拷貝

from http://blog.csdn.net/jackystudio/article/details/11553117


1.普通類型對象的拷貝

普通類型對象的拷貝很簡單,就是值的複製而已。比如:

  1. int _tmain(int argc, _TCHAR* argv[])  
  2. {  
  3.     int a=1;  
  4.     int b=a;  
  5.     return 0;  
  6. }  


2.類對象的拷貝

類對象的拷貝相比於普通類型的拷貝就複雜多了,它存在着各種成員變量。比如:

CopyTest.h

  1. class CCopyTest  
  2. {  
  3. public:  
  4.     CCopyTest(int _size):size(_size){}  
  5.     ~CCopyTest(void){}  
  6.   
  7. private:  
  8.     int size;  
  9. };  
main.cpp

  1. int _tmain(int argc, _TCHAR* argv[])  
  2. {  
  3.     CCopyTest a(3),b=a;  
  4.     return 0;  
  5. }  
程序運行正常,b.size=3,看起來好像和普通類型數據也沒什麼差。好吧,繼續往下看。


3.淺拷貝

我們再看一個例子。

main.cpp和上面一樣,CopyTest.h改爲:

  1. class CCopyTest  
  2. {  
  3. public:  
  4.     CCopyTest(int _size):size(_size){data=new int[size];}  
  5.     ~CCopyTest(void){delete []data;}//這裏進行了資源的釋放  
  6.   
  7. private:  
  8.     int size;  
  9.     int* data;  
  10. };  
這時運行發現程序掛掉了,或者崩潰或者未響應。爲什麼呢?

原因:

這時候淺拷貝的概念出來了。在將一個對象賦值給另外一個對象的時候,如果只是進行數據成員間值的簡單拷貝,比如上面這個例子,b.size=a.size; b.data=a.data。注意,data可是個指針啊,那麼此時a.data和b.data所指向的是同一塊內存空間。對象a在虛構的時候,a.data所指向的堆內存被釋放,這時再輪到對象b進行虛構,b.data所指向的堆內存再次要求被釋放,就會出現問題。

而例子2沒有異常的原因是因爲CopyTest這個類中沒有指針等引用其他資源的對象,所以這時淺拷貝和深拷貝對它而言並沒有區別。


4.深拷貝

深拷貝指的就是當拷貝對象中有對其他資源(如堆、文件、系統等)的引用時(引用可以是指針或引用)時,對象的另開闢一塊新的資源,而不再對拷貝對象中有對其他資源的引用的指針或引用進行單純的賦值,然後同步復拷貝開闢空間的值。

我們把上面的例子改一改。

main.cpp不變,CopyTest.h更改爲:

  1. class CCopyTest  
  2. {  
  3. public:  
  4.     CCopyTest(int _size):size(_size){data=new int[size];}  
  5.     ~CCopyTest(void){delete []data;}  
  6.   
  7.     CCopyTest(const CCopyTest& _copy):size(_copy.size){data=new int[size];memcpy(data,_copy.data,size);}//自定義拷貝構造函數  
  8.   
  9. private:  
  10.     int size;  
  11.     int* data;  
  12. };  

這裏還要注意一點,拷貝構造函數必須採用引用傳參的方式,而不能採用值傳參,因爲值傳參本身就要進行值拷貝,調用拷貝構造函數會引起無限循環嵌套,編譯器會報錯,棧溢出。VS和GCC中都會報錯。


5.總結

總之,在對進行對象拷貝時,當對象包含對其他資源的引用,如果需要拷貝這個對象所引用的對象,那就是深拷貝,否則即是淺拷貝。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章