2013-04-29 58 views
0

我有一個小功課問題。
下面的代碼給出:將值分配給已刪除的對象

int * p; 
p = new int; 
*p = 5; 

的問題是:爲什麼沒用做

p = 0; 
delete p; 

但有用做

delete p; 
p = 0; 

在我看來,兩者都是無用的。如果一個對象被刪除,則不能分配新的值。
我也在這兩種情況下得到一個Segmentation fault

+3

如果'delete p; p = 0;'給你一個段錯誤,你做錯了什麼。 – huskerchad 2013-04-29 02:51:00

+0

我嘗試之後返回'p'的值。 – user1170330 2013-04-29 02:52:05

+1

好吧,你去。 – huskerchad 2013-04-29 02:58:28

回答

5

爲什麼它是以下有用的:

delete p; 
p = 0; 

從Stroustrup的回答引用:Why doesn't delete zero out its operand?

考慮

delete p; 
// ... 
delete p; 

如果......部分不接觸然後第二個「刪除p」是一個嚴重的錯誤,即C++實現不能有效地保護自己免受(沒有不尋常的預防措施)。 由於根據定義刪除零指針是無害的,因此一個簡單的解決方案是「delete p;」做一個「p = 0;」在完成了其他所需的任何事情之後。但是,C++並不能保證這一點。 其中一個原因是delete的操作數不必是左值。考慮:

delete p+1; 
delete f(x); 

這裏,刪除的實現沒有指向它可以分配零的指針。這些例子可能是罕見的,但他們暗示,這是不可能保證any pointer to a deleted object is 0.'' A simpler way of bypassing that規則'是有兩個指向的對象:

T* p = new T; 
T* q = p; 
delete p; 
delete q; // ouch! 

C++明確允許的刪除實現零出左值操作數,我曾希望實現能夠這樣做,但是這個想法似乎並未在實現者中流行起來。 如果考慮歸零指針重要,可以考慮使用破壞功能:

template<class T> inline void destroy(T*& p) { delete p; p = 0; } 

考慮這個尚未另一個原因,儘量減少明確使用新的和依靠標準庫中的容器,處理刪除,等

注意,通過指針爲基準(以允許zero'd出指針)具有防止破壞()被調用用於一個右值的附加益處:

int* f(); 
int* p; 
// ... 
destroy(f()); // error: trying to pass an rvalue by non-const reference 
destroy(p+1); // error: trying to pass an rvalue by non-const reference 
0

這將指針設置爲null,然後調用刪除:

p = 0; 
delete p; 

這好像是說

delete 0; 

我想你所想的是,它被設置int值p指向歸零,但這樣做是這樣的:

*p = 0; 
2

回想一下,刪除0是允許的。因此,當你這樣做

p = 0; 
delete p; // Deleting zero is ignored 

你扔掉的p(從而開創了內存泄漏)舊值,然後調用delete 0,其中被忽略。

當你做到這一點,但是

delete p; 
p = 0; 

您使用舊值第一(解除分配的int),才把零出來。這是有道理的,因爲只要執行deletep的舊值就變得無用且危險。

+0

雖然C++編譯器會在您嘗試刪除它時忽略零值指針,也就是說會編譯時沒有錯誤。但是,這在運行時肯定會導致seg故障。 – Ozraptor 2013-04-29 02:55:09

+0

@Ozraptor不符合標準:允許「刪除0」和「空閒(NULL)」。這是一個正在運行的示例:[link](http://ideone.com/1PNXrt)。 – dasblinkenlight 2013-04-29 02:57:28

+0

@Ozraptor:標準明確允許:第5.3.5節第2段 – 2013-04-29 02:58:35

0

在第一種情況下,您將POINTER p的值分配爲'0',而不是p指向的int值。這就是爲什麼它是無用的(實際上會導致內存泄漏),並且當您嘗試從內存地址'0'中刪除時導致seg故障。編輯 - 實際上我剛剛瞭解到段錯誤並不是由'刪除0'引起的,而'刪除0'是根據標準忽略的,所以其他的事情正在造成這種情況。

在第二種情況下你正在釋放內存/對象指向的P(這應該是細),然後分配指針具有值「0」,這也應該是好了,所以不知道爲什麼你在那裏發生seg斷層?在實用性方面,過去認爲將free'd指針設置爲null或'0'值是一種很好的做法,因此您可以在取消引用它們之前對其進行測試。

0
p = NULL; 

p = 0; 

在你的指針,而不是它所指向的對象分配值的上述情況。

是一樣的。刪除函數用於釋放動態分配給對象的內存。

  1. 當你說

    delete p; 
    p = 0; 
    

    這好像是說免費分配給指針p 然後你說指針賦值爲NULL內存。哪個是對的。

  2. 在其他情況下,當你做到這一點

    p = 0; 
    delete p; 
    

    你是說分配指針第一爲NULL。現在指針p 未指向任何有效的動態分配的內存。所以後來 當你說delete p時,編譯器找不到任何內存來釋放 ,並因此引發分段錯誤。