簡體   English   中英

為什么不能僅從對象數組中刪除指針?

[英]Why can't I delete pointer alone from an array of objects?

A* p = new A[5];
delete &p[2];

//錯誤,為什么? 是否需要使用delete []p一起刪除?

p是一個指針( p == &p[0] ),但是p [0],p [1] ...是一種對象。 為什么p [n]不是指針?

那會實現什么? 您正在嘗試釋放單個A的空間,該空間位於較長的連續A陣列的中間。

這根本行不通,因為它與delete相反。

當您執行new[] ,運行時將為您提供足夠大的內存集來存儲對象數組。 如果該內存仍未“散布”,則運行時會要求操作系統將內存頁映射到進程的內存空間。

現在,如果您不再使用這些頁面,則可以“退還”它們; 但是,您必須對獲得的全部內存執行此操作。 那是因為釋放少於一頁的頁是行不通的(因為操作系統無法在其他任何地方分配頁),並且因為允許這種碎片將使頁表很大

這在free文檔中得到了反映:您只能通過freemalloc相同的地址來釋放內存。

刪除的內容必須與分配的內容完全匹配,不能進行部分刪除。 內存管理器通常根據返回的地址記錄有關分配的信息。 如果您傳遞其他地址來delete ,它將無法找到分配信息。

是和否:

是的 ,對new[]的調用必須與對delete[]的單個調用配對。

,不會“一起刪除”,因為結果只是一個實體(一個數組),而不是A的集合。 因此,您實際上並不會一起刪除任何內容。

,您不必同時結束數組所有元素的生命周期。 但是,此時您可能希望明確地調用析構函數,這將留給標准庫組件。

這使我們能夠:

您似乎想要實現的目標:
終止該數組的單個對象的生存期。 由於將結果作為具有某種魔術漏洞的數組沒有任何意義,因此您可能需要考慮使用std::vector<A>::erase進行處理。 這將刪除一個元素並將所有其他元素上移,以便結果表現為一個數組,其中一個元素被刪除而沒有留下孔。

delete適用於指針 (並且僅適用於指向動態分配的內存塊的指針),但是您沒有指針數組,因此delete不適用於數組元素,它只能適用於數組指針。 特別是delete []運算符。

如果要從數組中刪除一個元素,則必須迭代該數組,當到達要刪除的元素時,開始用下一個元素覆蓋該數組。 另外,您可能想要分配一個較短的新數組,然后在該處進行操作,然后刪除舊數組並將數組指針設置為新數組。

理想情況下, 您應該使用std::vector類,該類自動為您完成所有操作:

std::vector<A> v(5); // gives you a vector of 5 A elements
v.erase(v.begin() + 2); // erases the element at index 2

這種方式不太容易出錯,因此是首選方法,並且與容易出錯的手動方式一樣快捷,高效。

現在,如果您有一個指向元素的指針的數組/矢量,那將是另一回事,那么您必須確保delete該元素並將其從矢量中刪除。 自然,如果您使用智能指針,則只需從向量中刪除指針,指針將被自動刪除

為什么p [n]不是指針?

指針的[n]運算符只是引用帶偏移量的指針的快捷方式。 所以p[2]等於*(p + 2) 當取消引用指針時,您將獲得指向它所指向的對象的引用,在本例中為A實例。 因此, delete p[2]僅在是A指針數組而不是A實例的情況下才可以工作。 請注意,在您的情況下, &p[2]實際上是一個指針,它將與p + 2相同,因為&運算符將獲取引用的地址,但您不應在其上使用delete,因為它本身不會即使動態內存本身恰好位於此類內存中,也不會指向動態分配的內存。

正如您自己在問題p == &p[0]指出的那樣, p != p[0] 這意味着即使兩個都是相同地址的指針,也不應delete &p[0] 由於數組的內存已使用new []分配,因此應使用delete []釋放該內存,並且不應在數組或其任何元素上使用delete運算符。

&p[0]為您提供數組中第一個元素的地址,該地址與數組的開頭重合,但是p == &p[0]只是一個值比較。 p可能與&p[0] “相等”,但語義上並不相同 ,因為p是指向A []的指針,而&p[0]是指向A的指針。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM