我认为由于这个数组的每个元素都是一个指向结构体的指针,所以要删除42,首先需要调用delete arr[2]。
是的,您需要在arr [2]上使用delete以释放arr [2]指向的内存。
然后我会说arr [2] = arr [3]。
到目前为止还不错。
然后在arr [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
+
1 | b
+
2 | c
+
3 | d
+
4 | e
+
其中的字母代表new
所返回的不同内存地址。
这意味着,为了正确地删除索引为2的元素,您需要:
- 使用
delete
删除arr[2]
以避免内存泄漏,
- 覆盖
arr[2]
,并用某个其他仍然有效的地址替换它(在此步骤之前使用arr[2]
会触发一个seg-fault)
- 将复制到
arr[2]
的数组位置设置为null (如下所示)
- 减少您数组的长度(例如:
arr_cnt--;
)
换句话说:
delete arr[2]
arr[2] = arr[4]
arr[4] = NULL
--arr_cnt
图表现在应该是这样的:
idx *arr[] values in heap, due to using 'new' operator
+
0 | a
+
1 | b
+
2 | e
+
3 | d
+
4 | nil | 9 <
+
那么arr[3] = arr[4]是无效的
如果您按照这个图示进行操作,可能已经注意到使用delete
关键字会使两个条目都失效。换句话说,如果我们跳过第二张图并尝试使用您提出的delete arr[2]; arr[2] = arr[3]; delete arr[3]
逻辑,您最终会得到:
delete arr[2];
+
0 | a
+
1 | b
+
2 | c
+
3 | d
+
4 | e
+
arr[2] = arr[3];
+
0 | a
+
1 | b
+
2 | d
+
3 | d
+
4 | e
+
delete arr[3];
+
0 | a
+
1 | b
+
2 | d
+
3 | d
+
4 | e
+
因此,我决定尝试不使用delete关键字,而是执行arr[2]=arr[3]和arr[3]=arr[4],这样就可以了。但现在你存在内存泄漏的问题。在C++中,您必须像在C中一样始终要delete每个new。
那么我的问题是,为什么我不需要使用delete关键字来完成这个操作?您确实需要使用它。问题在于,您无意中使更多内容失效,并尝试使用已被释放的内存。当程序尝试访问这样的内存时,会导致段错误。我不记得Windows会显示什么准确消息,但可能是某种未处理的异常消息。(Segmentation fault倾向于是GNU / Linux术语)。
我认为如果我只是将arr[2]设置为arr[3],那么被arr[2]指向的结构体将丢失,我会出现内存泄漏。不是这样吗?您在这里是正确的。问题不在于您对new / delete关系的理解,而在于您所描述的赋值是浅复制,因此您删除了更多内容。
std::vector
替代。删除您想要删除的指针,然后从向量中 erase 它。 - Some programmer dude