考虑以下计划:
int main() {
while(...) {
int* foobar = new int;
}
return 0;
}
foobar
何时超出范围?
我知道在使用new
时,属性是在堆上分配的,需要使用delete
手动删除,在上面的代码中,它会导致内存泄漏。但是,范围呢?
我认为,一旦while循环终止,它就会超出范围,因为你不再能直接访问它了。例如,在循环终止后,你不能delete
。
答案 0 :(得分:13)
这里要小心,foobar
是while循环的本地,但堆上的分配没有作用域,只有在你调用delete时才会被破坏。
就编译器而言,变量和分配没有以任何方式链接。实际上,分配发生在运行时,因此编译器甚至都不会看到它。
答案 1 :(得分:9)
foobar
是一个局部变量,在块的末尾超出范围。
*foobar
是一个具有手动生命周期的动态分配对象。因为它没有作用域生命周期,所以这个问题没有任何意义 - 它不会拥有一个范围,它可以去哪个范围。它的生命周期是手动管理的,对象一直存在,直到你delete
。
你的问题带有偏见和先入为主的危险。最好以干净的头脑和开放的态度来接近C ++。只有这样,你才能最大限度地欣赏语言的奇迹。
以下是干净开放的方法:考虑 1)存储类(自动,静态,动态),2)对象生存期(作用域,永久性,手动),3)对象语义(值(副本)与引用(别名)),4)RAII和单一责任类。 清除你的想法 a)堆栈/堆,b)指针,c) new / delete ,d) 析构函数/复制构造函数/赋值运算符。
答案 2 :(得分:3)
这是一个非常棒的内存泄漏。堆栈上有一个变量,指向堆上分配的内存。当while循环范围结束时,在丢失对它的引用之前,需要删除堆上的内存。或者,如果您不想对内存管理大惊小怪,请始终使用智能指针来拥有堆上的原始内存并让它自行清理。
#include <memory>
int main() {
while(...) {
std::unique_ptr<int> foobar = new int;
} // smart pointer foobar deletes the allocated int each iteration
return 0;
}
答案 3 :(得分:2)
当程序到达while循环的右括号时,指针(foobar)将超出范围。因此,如果...
中的表达式仍然为真,则每次循环执行时内存都会泄漏,因为在截止括号中丢失了已分配对象的句柄。
答案 4 :(得分:1)
这里foobar
是占用堆栈内存的int
指针。您使用int
动态创建的new
实例将转到堆。当foobar
超出范围时,您将丢失对它的引用,因此您无法删除堆中分配的内存。
最好的解决方案是:
while(--)
{
int foobar;
}//it goes out of scope here. deleted from stack automatically!!
如果您仍想使用动态分配,请执行以下操作:
while(--)
{
int* foobar=new int;
//do your work here!
delete foobar; //This deletes the heap memory allocated!
foobar=NULL; //avoid dangling pointer! :)
}
答案 5 :(得分:0)
由于foobar在循环体中声明,因此在循环的每次迭代结束时都会超出范围。然后重新声明,并且一次又一次地分配新内存,直到循环结束。 foobar指向的实际对象永远不会超出范围。范围不适用于动态分配(又称堆)对象,仅适用于自动(堆栈)对象。
答案 6 :(得分:0)
foobar
超出范围。
您分配并分配给foobar
的内存正在泄露,因为它仍然在堆上分配,但程序中没有对它的引用。
答案 7 :(得分:-2)
Foobar指针在堆栈上创建,但新的int在堆上创建。在while循环的情况下,每次代码循环时,foobar都会失去范围。新创建的int在堆上持久存在。在每次迭代时,都会创建一个新的int,并重置指针,这意味着指针不再能访问堆上的任何先前的int。
在以前的每一个答案中,甚至在这一个答案中,似乎缺少的是堆落在范围之外。也许,我的术语不正确,但我知道在某些时候堆也被重置了。一旦程序不再运行,或者计算机关闭,它可能会发生,但我知道它发生了。
让我们从不同的角度来看待这个问题。我写了任何数量的程序,泄漏内存。这些年来,我拥有自己的电脑,我很肯定,我已经泄漏了超过2千兆字节的内存。我的电脑只有1千克的内存。因此,如果堆永远不会超出范围,那么我的计算机有一些神奇的记忆。你们其中一个人是否愿意解释堆的确切时间是否超出范围?