我试图准确理解c ++中删除的变量会发生什么。让我们说我有以下内容。
MyObject * obj;
for (int i = 0; i < 100000000; i++){
obj = someMethodThatReturnsNewMyObject();
obj->doSomething();
delete obj;
}
现在,在实例化时,obj
是指向MyObject
对象的指针。它首先由行obj = someMethodThatReturnsNewMyObject();
初始化。然后调用一些方法只是为了好玩,并删除obj
。现在我知道什么时候像这样被删除了,它指向的内存空间被清除,指针被设置为什么都没有。
但是,当for循环回来时,我重新初始化指针,导致它分配一个新的内存空间,obj
然后指向这个新空间。但是,指针本身从内存中移除了。在整个循环中,它只指向我指出的任何指向或指向任何东西(删除时)。
我的问题是:这是什么时候:指针本身,即指针占用的内存空间是什么时候被删除,为什么我不需要删除它,如果我需要删除记忆指向?
答案 0 :(得分:5)
指针(变量obj
)有automatic storage duration - 就像变量i
一样。编译器将发出代码以自动为这样的变量分配内存,并在超出范围时释放它;在调用任何析构函数之后。这个内存将在运行时来自堆栈,这使得分配和释放非常快。
顺便说一句,调用delete obj
不“将指针设置为无指向”。至少如果你的意思是指针被修改。它将继续具有之前的任何值,但该值将不再指向有效的内存位置。
答案 1 :(得分:2)
现在我知道什么时候像这样被删除了,它所指向的内存空间被清除了,
语言未指定运行时环境对内存的作用。该语言仅指定使用该内存是未定义的行为。
并且指针设置为不指向任何内容。
这是不正确的。指针的值保持不变。它指向的内存不再有效。
指针本身何时(即指针占用的内存空间)何时被删除
具体实施。在通常的实现中,当函数返回时,运行时environemnt会回收内存。根据语言,指针的生命周期结束时指针的生命周期结束。在范围结束后使用指针占用的内存是未定义的行为。
如果你有:
MyObject** ptr = NULL:
for (int i = 0; i < 100000000; i++){
// obj is defined in the scope of the for loop.
// It's life ends when the for loop ends.
MyObject* obj = someMethodThatReturnsNewMyObject();
obj->doSomething();
delete obj;
// Make ptr point to the address of obj.
ptr = &obj;
}
*ptr = NULL; // This is undefined behavior since ptr
// points to memory that is not valid any more.
答案 2 :(得分:1)
程序终止时指针本身被删除。您可能不需要删除指针本身,因为您正在重复使用它,并且它在存在期间在内存中占用相同的空间量。然而,指向的内存随着循环的每次迭代而被回收,以避免填满你的记忆。如果您的 for 循环只运行几次,这不会有问题,但是如果您在没有取消分配该空间的情况下进行大量循环,则可以可能填满你的记忆并使你的程序崩溃。
答案 3 :(得分:1)
delete
关键字删除指针指向的内存。它不会删除指针本身。
如何取消分配指针取决于它的声明位置。如果您的示例代码在方法/函数中,它将在堆栈上声明,并在方法/函数返回时释放。如果指针是一个全局变量,那么它将终生于你的程序。
答案 4 :(得分:1)
它指向的内存空间被清除,指针被设置为指向任何内容。
原谅错字,指针不改变了。它仍然指向调用delete
之前对象的位置。删除后,通过指针使用对象是“坏”。它可能会工作并访问以前的内容。它可能访问总垃圾(如内存重用)。通过指针调用方法很可能会跳转到空间,希望是segfalting而不是重新格式化磁盘。
您确实希望保留指针变量。每次迭代都会使用它。 delete
对于释放指针指向的对象中的内存(并运行任何析构函数)非常有用。
答案 5 :(得分:1)
当你这样做时:删除obj
然后,您要将obj指向的内存位置标记为要删除,并将返回给系统。
Its a bit tricky here larger chucks are mmap'd
和smaller ones are managed by heap and deleting it will not be reflected in the system unless it is the topmost
。如果它不是堆中的最顶层,那么brk / sbrk将不会被移动,并且当您下次询问/分配大小相同或小于标记为要删除的大小时,将重新使用它。算法有点复杂,但这就是要点。
在你的代码中,在第二次迭代中,obj可以指向一个完全不同的块/块。