C++指针和动态数组以及删除运算符

C++ Pointers and Dynamic Arrays and Delete Operator

本文关键字:删除 运算符 数组 指针 动态 C++      更新时间:2023-10-16

好的,所以我将布置两个程序。 两者都是使用指针和 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.或任何特定执行的内存地址。所以,问题是: 为什么在第二种情况下不能使用删除运算符? 我不想有内存泄漏;我不希望指针悬空。 如果我只是说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

您必须deletenew获得的指针。但是,在第二个代码中,您执行了更改指针p++。因此,您尝试delete一个没有从new中获得的指针,并delete崩溃。

要修复此类错误,切勿使用new。而是使用std::vector<int> p;.因为你永远不需要new所以你不能忘记一个delete

问题正在更改p++中的p。 您应该始终存储(删除)原始指针。喜欢这个:

#include <iostream>
int main()
{
int *original = new int[5];
int *p = original;
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
int x = *p;
p++;
*p = x + 1;
}
std::cout << std::endl;
delete [] original;    
return 0;
}