我认为,因为此数组中的每个元素是一个指针,指向的结构,则为了删除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