C++ 当堆上的数据超出范围时,堆上的数据指针是否被删除?
我一直听说在堆栈上分配了一个匿名临时变量,它在对包含表达式的求值结束时被销毁 因此,如果我们具备以下条件:C++ 当堆上的数据超出范围时,堆上的数据指针是否被删除?,c++,C++,我一直听说在堆栈上分配了一个匿名临时变量,它在对包含表达式的求值结束时被销毁 因此,如果我们具备以下条件: //A function defined as int foo(int* p) { ... // writing this explicitly to avoid confusion with the question delete p; } int main() { foo(new int); // anonymous pointer? return 0; }
//A function defined as
int foo(int* p)
{ ...
// writing this explicitly to avoid confusion with the question
delete p;
}
int main()
{
foo(new int); // anonymous pointer?
return 0;
}
现在,当从main()调用foo时,指向heap元素的匿名指针被复制到p,这意味着有两个指向同一heap元素的指针。即使我们最终在foo中使用delete来删除数据并将指针设置为nullptr,我们仍然会留下指向垃圾的匿名指针。这样的匿名指针超出范围时是否被清除
这种情况类似于使用shared_ptr的构造函数表单,该表单还从调用者获取指向某些数据的原始匿名指针,以构造一个共享指针,其中指针值被复制到构造函数。当这些匿名指针超出范围时是否设置为NULL?否,它们不会自动删除。分配了自动存储的对象和POD被删除。分配了
new
的对象或POD不可用
我们仍然有指向垃圾的匿名指针。这样的匿名指针超出范围时是否被清除
它是匿名的,因此没有定义值可能包含的行为。指针是C++和C概念,编译器所用的中介没有用任何标准来描述。但是如果你想知道编译器会发生什么,你可以反汇编目标代码。很可能表示指针的值可能已经被存储在堆栈上,并且在代码< >主< <代码> >时返回(指针本身,而不是<代码> INT/COD> >)。指针不是共享指针,在C++中默认不会自动删除。p>
void fn()
{
YourClass LocalObject;
...
} // LocalObject goes out of scope here and is destroyed automatically
void fn2()
{
YourClass *PointedObject = new YourClass();
} // Object pointed to by the pointer is not destroyed.
实际上,
PointedObject
在某个时候需要删除。完成后,您可能会返回指针或其他东西并调用delete
。我想我在您的问题中发现了一个误解。然而,我可能错了;如果是这样,则不予理会
你问:
即使我们最终在foo中使用delete来删除数据和设置
指向nullptr的指针,我们仍然剩下匿名指针
指向垃圾。这样的匿名指针被清除了吗
超出范围
这种情况类似于使用shared_ptr的构造函数形式
这也会将调用方指向某些数据的原始匿名指针
构造一个共享指针,将指针值复制到
构造器。这样的匿名指针在退出时是否设置为NULL
范围
从这些问题来看,您可能会有这样的印象:将指针设置为null(“清除”它)是释放它指向的任何内容的一个重要部分。在C++中,情况并非如此。要释放p
指向的对象,请执行删除p代码>,故事结束。你也可以说p=nullptr如果您想确保以后查看p
的任何人都意识到它是无效的,那么无论您是否这样做,它之前指向的对象都会消失
在这个假设代码中:
int foo(int* p)
{
//some content
delete p;
}
int main()
{
foo(new int); // anonymous pointer?
}
int foo(int* p)
{
//some content, but no delete p
}
int main()
{
foo(new int); // anonymous pointer?
}
没有内存泄漏,一切正常。传递到foo
的临时匿名指针是否在foo
返回后引用垃圾的问题毫无意义,因为临时指针在该点上实际上是不可见的,并且不会进一步参与程序所做的任何事情(原始指针没有析构函数)
但在这个假设代码中:
int foo(int* p)
{
//some content
delete p;
}
int main()
{
foo(new int); // anonymous pointer?
}
int foo(int* p)
{
//some content, but no delete p
}
int main()
{
foo(new int); // anonymous pointer?
}
不会删除匿名新int
,因此内存泄漏。与POD无关。所有自动存储对象都被“删除”。除此之外,它们不会被自动删除。
答案是无用的。重要的是要理解,尽管delete
使用指针,但操作实际上是在它指向的内存上执行的。因此,如果有两个(或三个,或四个,或n个)指针都指向同一个动态分配的对象,只要对其中一个对象调用delete
,就不会泄漏内存。当它超出范围时,它就消失了。无法命名。尝试(例如预先使用绑定到它的引用)是未定义的行为。所以问它的值是空指针还是空指针是没有意义的。指针值不存在。将new与delete配对,或将所有权委托给std::unique\u ptr/std::shared\u ptr(没有自动删除指针)在删除后将指针设置为nullptr
,这在某些情况下是一种很好的做法,因为这会使指针明显不再有效,但正确的内存管理并不需要它。或者换句话说,在C++中,设置一个空指针对它指向的事物没有影响。这与C#和Java不同,在C#和Java中,做同样的事情可能会使对象成为垃圾收集的候选对象。人们对你的问题感到困惑,因为他们认为你的意思是删除不存在。在编写代码时,不会导致内存泄漏。谢谢。我理解你的评论。我所说的删除并不是指针指向的数据。我想问的是,当临时指针超出范围时,指针本身是否被删除。@avish指针位于堆栈上,因此不需要删除。一般来说,如果不使用new
,一切都很好。指针只是一个数字;当一个函数超出范围时发生的情况与int
函数发生的情况相同代码>,这将泄漏一个int*
,但这将是一件非常奇怪的事情。