深淺拷貝及釋放

2021-07-05 10:31:37 字數 1725 閱讀 4143

請看下面的程式,說說會出現什麼問題?

#include

#include

#include

using   namespace   std; 

class   cdemo   ; 

~cdemo() 

; char*   str; 

}; int   main(int   argc,   char**   argv)  

這個程式在退出時,會出問題,什麼問題?重複delete同一片記憶體,程式崩潰。

我們把析構函式改為如下,可以更清楚的看到這一點:

~cdemo() 

}; 執行時我們發現列印如下資訊:

&cdemo0=000309d8,       str=000307a8

&cdemo1=0013ff70,       str=000307a8

也就是說,發生了cdemo類的兩次析構,兩次析構str所指向的同一記憶體位址空間(兩次str值相同=000307a8)。

為什麼?

《程式設計師面試寶典》第二版,p99,有句解釋「vector物件指標能夠自動析構,所以不需要呼叫delete a1,否則會造成兩次析構物件」

我切以為這句話說的有點不妥。任何物件如果是通過new操作符申請了空間,必須顯示的呼叫delete來銷毀這個物件。所以「delete   a1; 」這條語句是沒有錯誤的。

這句話「vector*a1=new   vector(); 」定乙個指標,指向 vector,病用new操作符進行了初始化, 我們必須在適當的時候釋放a1所佔的記憶體空間,所以「delete   a1; 」這句話是沒有錯誤的。另外,我們必須明白一點,釋放vector物件,vector所包含的元素也同時被釋放。

那到底那裡錯誤?

這句a1的宣告和初始化語句「vector*a1=new   vector(); 」說明a1所含元素是「cdemo」型別的,在執行「a1->push_back(d1); 」這條語句時,會呼叫cdemo的拷貝建構函式,雖然cdemo類中沒有定義拷貝建構函式,但是編譯器會為cdemo類構建乙個預設的拷貝建構函式(淺拷貝),這就好像任何物件如果沒有定義建構函式,編譯器會構建乙個預設的建構函式一樣。

正是這裡出了問題。a1中的所有cdemo元素的str成員變數沒有初始化,只有乙個四位元組(32位機)指標空間。

「a1->push_back(d1);」這句話執行完後,a1裡的cdemo元素與d1是不同的物件,但是a1裡的cdemo元素的str與d1.str指向的是同一塊記憶體,這從後來的列印資訊就可以看出來。

我們知道,區域性變數,如「cdemo   d1; 」 在main函式退出時,自動釋放所佔記憶體空間,

那麼會自動呼叫cdemo的析構函式「~cdeme」,問題就出在這裡。

前面的「delete   a1;」已經把 d1.str 釋放了(因為a1裡的cdemo元素的str與d1.str指向的是同一塊記憶體),main函式退出時,又要釋放已經釋放掉的 d1.str 記憶體空間,所以程式最後崩潰。

解釋清楚了。

這裡最核心的問題歸根結底就是淺拷貝和深拷貝的問題。如果cdemo類新增乙個這樣的拷貝建構函式就可以解決問題:

cdemo(const   cdemo   &cd) 

;這就是深拷貝。

或者這樣用:

vector*a1=new   vector(); 

a1->push_back(&d1); 

那麼在    「delete   a1;」 a1釋放,同時a1裡面包含的元素(」cdemo*「型別,仍然是乙個指標,4位元組空間)。

JS 變數及深淺拷貝

js變數分為基本型別和引用型別 基本型別資料報括number,string,boolean,null,undefined五種型別 引用資料型別包括array,date,regexp,function等,統稱為object型別。js變數的儲存方式 基本型別變數儲存在記憶體的棧中,棧內分別儲存著變數的識...

深淺拷貝以及深淺拷貝的方法

先考慮一種情況,對乙個已知物件進行拷貝,編譯系統會自動呼叫一種建構函式 拷貝建構函式,如果使用者未定義拷貝建構函式,則會呼叫預設拷貝建構函式。執行結果 呼叫一次建構函式,呼叫兩次析構函式,兩個物件的指標成員所指記憶體相同,name指標被分配一次記憶體,但是程式結束時該記憶體卻被釋放了兩次,會造成記憶...

拷貝和深淺拷貝

當list2為list的拷貝物件時,list內的可變資料型別變化,list2變化 list內的不可變資料型別變化,list2變化。總之 list變化list2一定變化 list 1,2,3,4,list2 list print list print list2 1,2,3,4,5 1,2,3,4,5...