我認爲,因爲此數組中的每個元素是一個指針,指向的結構,則爲了刪除42,我必須先調用刪除ARR [2]
是的,你將在arr[2]
上使用delete
以釋放arr[2]
指向的內存。
那麼我會說ARR [2] = ARR [3]
到目前爲止好。
,然後改編刪除[3]
這是問題就在這裏。假設你有這樣的代碼:
int arr_cnt = 5;
int *arr[arr_cnt];
for(int i = 0; i < arr_cnt; ++i)
arr[i] = new int(i+arr_cnt); // using ints for simplicity, but concept is the same
你的陣列arr
現在看起來是這樣的:
idx *arr[] values in heap, due to using 'new' operator
+-----+
0 | a---|----> 5
+-----+
1 | b---|----> 6
+-----+
2 | c---|----> 7
+-----+
3 | d---|----> 8
+-----+
4 | e---|----> 9
+-----+
其中字母代表了new
返回不同的內存地址。
這意味着,在指數2正常刪除的元素,你需要:
- 上
arr[2]
使用delete
,以避免內存泄漏,
- 覆蓋
arr[2]
與這仍然有效一些其他的地址(使用arr[2]
現在會觸發段錯誤)
- 無效陣列位置複製到
arr[2]
(見下文)
- 遞減數組的長度(例如
arr_cnt--;
)
換句話說:
delete arr[2]; // step 1, address 'c' no longer valid
arr[2] = arr[4]; // step 2, arr[2] is now 'e', which points to 9 just like arr[4]
arr[4] = NULL; // step 3, arr[4] is now invalid
--arr_cnt; // step 4
現在,該圖是這樣的:
idx *arr[] values in heap, due to using 'new' operator
+-----+
0 | a---|----> 5
+-----+
1 | b---|----> 6
+-----+
2 | e---|-----------+ // address 'e' used to be in arr[4]
+-----+ |
3 | d---|----> 8 |
+-----+ |
4 | nil | 9 <--+
+-----+
然後常用3 [3] = ARR [4]。這是行不通的
如果你按照圖中,你可能已經注意到,現在使用delete
都意味着你是無效的兩個條目。換句話說,如果我們跳過第二個圖,並嘗試delete arr[2]; arr[2] = arr[3]; delete arr[3]
邏輯,你結束了:
delete arr[2];
+-----+
0 | a---|----> 5
+-----+
1 | b---|----> 6
+-----+
2 | c---|----> ? // invalidated
+-----+
3 | d---|----> 8
+-----+
4 | e---|----> 9
+-----+
arr[2] = arr[3];
+-----+
0 | a---|----> 5
+-----+
1 | b---|----> 6
+-----+
2 | d---|-+
+-----+ |
3 | d---|-+--> 8 // both have the same address, so point to the same place
+-----+
4 | e---|----> 9
+-----+
delete arr[3];
+-----+
0 | a---|----> 5
+-----+
1 | b---|----> 6
+-----+
2 | d---|-+
+-----+ |
3 | d---|-+--> ? // both invalid now, but not set to null
+-----+
4 | e---|----> 9
+-----+
所以我決定嘗試沒有刪除關鍵字,只是不常用3 [2] = ARR [3]和arr [3] = arr [4],並且工作。
但現在你有內存泄漏。你總是要delete
每new
在C++中,就像你總是要free
每malloc
在C.
所以我的問題是,爲什麼我沒有使用delete關鍵字才能做到這一點。
您做必須使用它。問題在於你的失效比你想像的要多,最終試圖與已被釋放的內存一起工作。當程序嘗試像這樣訪問內存時,會導致分段錯誤。我不記得Windows會顯示的確切消息,但它可能是某種未處理的異常消息。 (分割錯誤往往是GNU/Linux術語。)
我在想,如果我只是將arr [2]設置爲arr [3],那麼arr [2]指向的結構將會丟失,我會得到一個內存泄漏。情況並非如此嗎?
你在這裏是正確的。問題不在於你對new
/delete
關係的理解,只是你描述的任務是淺副本,並且最終刪除了超過預期的結果。
改爲使用'std :: vector'。從矢量中刪除要刪除的指針,然後[擦除](http://en.cppreference.com/w/cpp/container/vector/erase)。 –
其實,我試圖從學校學習一個概念,所以我需要這樣做。 –
請記住回來接受你認爲對你最有幫助的答案。它有益於你,海報和整個社區。 – ray