2011-12-06 57 views
18

我讀過delete[]運算符是需要的,因爲運行時環境沒有保存有關分配的塊是否是需要析構函數調用的對象數組的信息,但它實際上保留了有關內存中分配的位置的信息塊存儲,當然還有塊的大小。
只需要多一點元數據就可以記住是否需要在刪除時調用析構函數,爲什麼不這樣做?爲什麼運行時環境不能決定應用刪除或刪除[]而不是程序員?

我很確定有一個很好的解釋,我沒有質疑它,我只是想知道它。

+0

你問爲什麼有'delete []'而不是'delete'處理數組的重新分配和銷燬? –

+0

這是一個小的成本,但是,付出的收益也很小。 –

+2

除非標準明確指出分配的大小存儲在某處(我懷疑它),並不總是需要存儲分配的大小。以下例子:'int * p = new int;'以一種定義的方式刪除它的唯一方法是調用'int *'上的delete。因此,從你知道它是'int'的事實隱含地知道這個大小。 (注意,在void *上調用delete是UB:http://stackoverflow.com/a/941959/239916)。 –

回答

3

這裏有兩件事需要清理。

第一:假設malloc保持你問的精確大小。

不是。 malloc只關心提供足夠大的塊。儘管出於效率的原因,它可能不會佔用太多,但仍可能會給你一個「標準」大小的塊,例如2^n字節塊。因此實際的大小(如實際分配的對象的數量)實際上是未知的。

二:「額外位」要求

事實上,知道它是否是一個數組的一部分,都將僅僅是一個額外的比特需要給定對象的信息。按道理。

就實現而言,儘管如此:你會在哪裏放置那個位?

爲對象本身分配的內存應該可能不會被觸及,對象畢竟使用它。那麼?

    一些平臺
  • ,這可能是(有些平臺忽略位的部分)保持在指針本身,但這不是便攜式
  • 所以它需要額外的存儲,至少一字節,除了對齊問題可能達到8個字節。

示範: (不能令人信服由某事所指出的,見下文)

// A plain array of doubles: 
+-------+-------+------- 
| 0 | 1 | 2 
+-------+-------+------- 

// A tentative to stash our extra bit 
+-------++-------++-------++ 
| 0 || 1 || 2 || 
+-------++-------++-------++ 

// A correction since we introduced alignment issues 
// Note: double's aligment is most probably its own size 
+-------+-------+-------+-------+-------+------- 
| 0 | bit | 1 | bit | 2 | bit 
+-------+-------+-------+-------+-------+------- 

Humpf!

編輯

因此,在大多數平臺上(如地址做的事),你將需要「擴展」每個指針,實際上增加一倍它們的大小(對齊問題)。

所有指針的大小隻有兩倍是可以接受的,這樣才能存儲額外的位數?對於大多數人來說,我想它會是。但是C++並不是爲大多數人設計的,它主要是爲那些關心性能,無論是速度還是內存的人設計的,因此這是不可接受的。編輯

END

那麼,什麼是正確的答案?正確的答案是恢復類型系統丟失的信息是昂貴的。不幸。

+1

對於每個數組元素,您都不需要存儲一點數據,因爲它無法「刪除」數組內的指針。只有第一個元素需要能夠確定整個數組是否跟隨它。 – sth

+0

@sth:真的,示範是有缺陷的......我給了我很多的愛,我的ASCII圖紙:(我糾正了,謝謝你的通知 –

+0

再一次,你檢查了殯葬目的堆分配器的開銷嗎? –

10

我認爲原因是C++不會強迫你進入任何你不想要的東西。它會增加額外的元數據,如果有人沒有使用它,那麼與C++語言的設計目標相比,額外的開銷會被強加於他們。

當你想要你描述的功能時,C++ 確實提供了提供的一種方法。它被稱爲std::vector,你應該幾乎總是喜歡它,另一種容器,或一個智能指針超過原始newdelete

+0

大概......雖然有人會說用C數組的語義已經打破所以它只是從那裏上。我擔心把這個規模放大是一個過早的微觀優化。 –

+0

我不認爲這是個問題。 –

+0

關於'std :: vector' ...不完全是因爲它可以動態增長。一個更簡單的容器可以工作。儘管如此,足夠接近。 –

4

C++讓您儘可能高效,因此如果他們確實需要跟蹤塊中的元素數量,那麼每個塊只需要使用額外的4個字節。

這可能對很多人有用,但它也會阻止不介意放置[]的人的總效率。

它與C++和Java的區別很相似。 Java可以更快地編程,因爲您不必擔心垃圾收集,但是如果編程正確,C++可以更高效並使用更少的內存,因爲它不必存儲任何這些變量,您可以決定何時刪除內存塊。

+2

現在去檢查任何通用堆分配器,並查看每個分配有多少開銷。對於每個分配的數字,如16-64字節,我不會感到驚訝,因此大小爲4-8字節將不會有人注意。而且,可能大多數分配器無論如何都會跟蹤分配。 –

4

它基本上歸結爲語言設計不希望對實現者施加太多限制。對於::operator delete(),許多C++運行時對::operator new()free()使用malloc()(或多或少)。標準malloc/free不提供記錄多個元素所必需的簿記,也沒有提供在free時間確定malloc的大小的方法。從C/C++的角度來看,在new Foomalloc之間爲每個單獨的對象添加另一級別的內存操作在複雜性/抽象性方面有了很大的提高。除此之外,將這種開銷添加到每個對象都會搞砸一些內存管理方法,這些方法的設計知道對象的大小。

相關問題