假设我有以下代码段。
int main()
{
int num;
int* cost;
while(cin >> num)
{
int sum = 0;
if (num == 0)
break;
// Dynamically allocate the array and set to all zeros
cost = new int [num];
memset(cost, 0, num);
for (int i = 0; i < num; i++)
{
cin >> cost[i];
sum += cost[i];
}
cout << sum/num;
}
` `delete[] cost;
return 0;
}
虽然我可以在while循环中移动delete
语句
对于我的代码,出于理解的目的,我想知道代码在编写时会发生什么。每次使用运算符new
时,C ++是否会分配不同的内存空间?
运营商delete
是否仅删除最后分配的cost
数组?
答案 0 :(得分:22)
每次使用operator
new
时,C ++是否会分配不同的内存空间?
是
运营商
delete
是否仅删除最后分配的cost
数组?
是。
你已经失去了指向其他人的唯一指针,因此他们不可避免地被泄露了。要避免此问题,请不要兼顾指针,而是使用RAII自动管理动态资源。 std::vector
在这里是完美的(如果你真的需要一个数组;你的例子可以继续阅读并重新使用单个int
)。
答案 1 :(得分:7)
我强烈建议你不要使用&#34; C成语&#34;在 C ++ 程序中。让std
图书馆为你工作:这就是为什么它在那里。如果你想要&#34; n 整数的数组(向量),&#34;那就是std::vector
的全部内容,和它&#34;附带电池。&#34; 你不必喋喋不休地使用&#34;设置最大尺寸&#34;或&#34;将其设置为零。&#34;你只需使用&#34;这个的东西,&#34; ,你的内部工作你不必[关心...]关心,知道它已经经过彻底的设计和测试。< / p>
此外,当您这样做时,您将在C ++的现有内存管理框架内工作。特别是,你没有做任何事情&#34;带外&#34;在你自己的应用程序中#34;标准库不知道,哪些可能(!!)它。&#34;
C ++为您提供了一个非常全面的快速,高效,强大且经过良好测试的功能库。 利用它。
答案 2 :(得分:5)
代码中没有cost
数组。在您的代码cost
中是指针,而不是数组。
代码中的实际数组是由重复的new int [num]
调用创建的。每次调用new都会创建一个新的,独立的无名数组对象,该对象位于动态内存中的某个位置。新数组一旦由new[]
创建,就可以通过cost
指针访问。由于数组是无名,因此cost
指针是唯一的链接,它指向由new[]
创建的无名数组。您没有其他方法可以访问该无名数组。
每次在你的周期中执行cost = new int [num]
时,你就会创建一个全新的,不同的数组,打破从cost
到前一个数组的链接并使cost
指向新的。
由于cost
是您唯一的旧数组链接,因此旧数组无法访问。永远丢失对旧阵列的访问权限。它变成了内存泄漏。
正如您自己正确陈述的那样,您的delete[]
表达式仅释放最后一个数组 - 最后一个cost
最终指向该数组。当然,只有在代码执行cost = new int [num]
行时才会出现这种情况。请注意,您的周期可能会在不进行单个分配的情况下终止,在这种情况下,您将delete[]
应用于未初始化(垃圾)指针。
答案 3 :(得分:3)
是。因此,除了最后一次迭代之外,每次迭代都会出现内存泄漏。
使用new
时,会分配一块新的内存。将new
的结果分配给指针只会更改此指针指向的内容。它不会自动释放此指针之前引用的内存(如果有的话)。
答案 4 :(得分:3)
首先关闭这一行是错误的:
memset(cost, 0, num);
假设int只有一个char长。更典型的是四个。如果你想使用memset初始化数组,你应该使用这样的东西:
memset(cost, 0, num*sizeof(*cost));
或者更好的是转储memset并在分配内存时使用它:
cost = new int[num]();
正如其他人指出的那样,删除被错误地放置并且将泄漏由其相应的新分配的所有内存,除了最后一个。把它移到循环中。
答案 5 :(得分:1)
每次为阵列分配新内存时,先前分配的内存都会泄露。根据经验,您需要释放内存的次数与分配的次数相同。