好的,所以我要布置两个程序。两者都是使用指针和 new 运算符的动态数组。但是有人似乎不喜欢删除运算符。
#include <iostream>
int main()
{
int *p;
p = new int[5];
for (int i = 0; i < 5; i++)
{
p[i] = 25 + (i * 10);
std::cout << p[i] << " ";
}
std::cout << std::endl;
delete [] p;
p = NULL;
return 0;
}
这是第一个程序。它非常喜欢删除运算符。现在不喜欢删除运算符的程序:
#include <iostream>
int main()
{
int x;
int *p;
p = new int[5];
*p = 4;
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
x = *p;
p++;
*p = x + 1;
}
std::cout << std::endl;
delete [] p;
p = NULL;
return 0;
}
这个程序编译得很好。但在执行期间,它会抛出错误 - free(): invalid pointer: 0xfdb038
.. 或该特定执行的任何内存地址。所以,问题是:
为什么不能在第二种情况下使用 delete 运算符?
我不想有内存泄漏;我不希望指针悬空。
如果我只是说 p = NULL;
,那么 p = 0
,但我相信指针仍然悬空?但我不确定。提前致谢。
最佳答案
看看第二段代码中的这个循环:
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
x = *p;
p++;
*p = x + 1; // <--- Here
}
请注意,在这一行中,您写入了当前由 p
指向的内存地址。因为您总是递增 p
然后写入它,所以您最终会在您为 p
分配的区域末尾注销。 (如果我们将 pOrig
想象成指向 p
最初指向的位置的指针,那么这将写入 pOrig[1]
,pOrig[2 ]
、pOrig[3]
、pOrig[4]
和 pOrig[5]
,最后一次写入超过区域的末端)。这会导致未定义的行为,这意味着实际上任何事情都可能发生。这是个坏消息。
此外,delete[]
假定您传递的是指向您分配的数组的第一个元素的指针。由于您在该循环中递增了 p
多次,因此您试图 delete[]
一个不在分配数组底部的指针,因此问题。
要解决此问题,请不要在递增后写入 p
,并存储指向用 new[]
分配的原始数组的指针,以便您可以释放它而不是修改后的指针 p
。
关于C++ 指针和动态数组以及删除运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37901560/