2010-02-27 16 views
6

如果我這樣做:刪除如何區分內置數據類型和用戶定義的數據類型?

// (1.) 
int* p = new int; 
//...do something 
delete p; 

// (2.) 
class sample 
{ 
public: 
sample(){} 
~sample(){} 
}; 
sample* pObj = new sample; 
//...do something 
delete pObj; 

那麼請問C++編譯器知道下面該對象delete是內置的數據類型或類對象?

我的另一個問題是,如果我new指針的int的數組,然後我delete []再怎麼不知道編譯器的內存塊的大小,以取消分配?

回答

4
  1. 編譯器知道的類型的指向的對象,因爲它知道指針的類型:

    • pint*,因此指向的對象將是一個int
    • pObjsample*,因此指向的對象將是sample
  2. 編譯器知道你int* p指向單一int對象或數組(int[N])。這就是爲什麼必須記住使用delete[]而不是delete陣列。

    要取消分配的內存塊的大小以及最重要的是要銷燬的對象的數量是已知的,因爲new[]將它們存儲在某處,並且delete[]知道從哪裏檢索這些值。 This question from C++ FAQ Lite顯示實施new[]delete[]的兩種常用技術。

4

它知道它們之間的區別,因爲指針的類型,你傳遞給它:它是不確定的行爲傳遞比你,如果分配的(除非你可以傳遞一個指向基類的不同的指針類型當然是析構函數是virtual)。

陣列的大小將存儲在某個地方。這就像在C中,你可以malloc一定量的內存,之後免費 - 運行時將必須設法知道以前分配的大小。

例如,它可以存儲之前所分配的緩衝器元件的計數。標準明確地允許編譯器在陣列分配的情況下,通過不同的請求大小,以分配函數(operator new[]) - 這可以通過編譯器使用粘計成,並抵銷了大小由new表達式返回的地址那個櫃檯。

1

它不!

所有做什麼delete的是,它調用的類型,這是原始類型的情況下,「不採取行動」的析構函數。然後,它通過指針::operator delete(或者,如果你喜歡一個重載的版本),並且那操作返回內存(內存管理的問題)。即使您願意,您也可以用C++輕鬆編寫自己的內存管理器,該語言默認提供一種內存管理器!

1
  1. 編譯器知道對象的類型被刪除,並寫入不同的代碼爲您實現正確的結果:
    • 刪除p可以調用與int的大小,運行時間刪除。
    • 刪除pObj可以調用pObj->〜樣品()首先,然後用樣品的大小
  2. 我認爲與陣列刪除,對於陣列的大小的潛在價值,所以它可能是整個數組一次被刪除。
1

那麼請問C++編譯器知道對象下面的刪除是內置的數據類型或類對象?

因爲在編譯時編譯器會跟蹤每個對象的類型並植入相應的代碼。

我的另一個問題是,如果我新建一個指向int數組的指針,然後刪除[],那麼編譯器如何知道內存塊的大小以解除分配?

它沒有。這由運行系統保持跟蹤。
當您動態分配數組時,運行時庫將對象的大小與對象相關聯,因此當它刪除它時,它知道(通過查找關聯的值)大小。

但我想你想知道它是如何做的關聯?
這取決於系統並且是一個實現細節。但是一個簡單的策略是在前四個字節中分配一個額外的4字節存儲大小,然後返回一個指向分配的第4個字節的指針。當你刪除一個指針時,你知道指針的大小是4個字節。注意:我並不是說你的系統正在使用這種技術,但它是一個有策略的問題。

0

對於問題的第一(非陣列)的一部分,上述指示編譯器插入代碼以解除分配基於所述指針類型字節的適當數目的答案,不太提供爲我清除答案...刪除操作符1)調用析構函數(如果適用),然後2)調用「operator delete()」函數......它是運算符刪除,實際上取消分配。我可以看到編譯器生成的代碼在第(1)部分扮演角色,即。必須插入析構函數的目標地址。但在第(2)部分中,它是一個處理解除分配的預先存在的庫函數,那麼它將如何知道數據的大小?全局運算符delete - 我相信在所有情況下都使用它,除非程序員定義了一個類成員/重載全局版本 - 只接受指定數據開始的void *參數,所以它可以甚至不會傳遞數據大小。 我讀過的東西指出編譯器生成的代碼思想,以及暗示非數組的全局運算符刪除簡單地使用free()的事情,即。它不是通過指針類型知道數據大小,而是通過在數據本身之前查看幾個字節,其中大小將被new/malloc隱藏。後者是唯一對我有意義的解決方案,但也許有人可以給我不同的啓發...

相關問題