当超出范围时,是否删除了堆上数据的指针?

时间:2014-10-07 19:24:33

标签: 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;
}  

现在当从main()调用foo时,指向heap元素的匿名指针被复制到p,这意味着有两个指向同一堆元素的指针。即使我们最终使用foo中的delete删除数据并将指针设置为nullptr,我们仍然留下指向垃圾的匿名指针。当它超出范围时,这样的匿名指针是否被清除?

这种情况类似于使用shared_ptr的构造函数形式,该形式还将来自调用者的原始匿名指针转换为某些数据,以构造一个共享指针,其中指针值被复制到构造函数中。当这些匿名指针超出范围时,它们是否设置为NULL?

3 个答案:

答案 0 :(得分:2)

我想我在你的问题中闻到了一种误解。但是,我可能错了;如果这样无视。

你问这个:

  

即使我们最终在foo中使用delete来删除数据并进行设置   指向nullptr的指针,我们仍然留有匿名指针   指着垃圾。这样的匿名指针是否被清除   超出范围?

     

这种情况类似于使用shared_ptr的构造函数表单   它还将来自调用者的原始匿名指针转换为某些数据   构造一个共享指针,指针值被复制到   构造函数。这些匿名指针在外出时是否设置为NULL   范围?

从这些问题来看,似乎你可能会认为设置一个指向null(“清除”它)的指针是释放它所指向的任何东西的重要部分。在C ++中,情况并非如此。要释放对象p,请执行delete p;,故事结束。你可能之后也会说p = nullptr;如果你想确保任何看到p的人后来意识到它是无效的,但无论你是否这样做,它之前指出的对象是走了。

所以在这个假设的代码中:

int foo(int* p)
{
   //some content
   delete p;
}

int main()
{
  foo(new int); // anonymous pointer?
}

没有记忆被泄露,一切都很好。传递给foo的临时匿名指针是否在foo返回后引用垃圾的问题是没有意义的,因为临时在该点实际上是不可见的,并且不会进一步参与程序所做的任何事情(原始的)指针没有析构函数。)

但是在这个假设代码中:

int foo(int* p)
{
   //some content, but no delete p
}

int main()
{
  foo(new int); // anonymous pointer?
}

什么都不会删除匿名new int,所以你有内存泄漏。

答案 1 :(得分:0)

不,它们不会自动删除。分配有自动存储的对象和POD是。分配有new的对象或POD不是。

  

我们仍然留下指向垃圾的匿名指针。当它超出范围时,这样的匿名指针是否被清除?

它是匿名的,因此没有针对值包含的内容定义的行为。指针是C ++和C概念,因此编译器使用的中间体不会被任何标准描述。但是如果你想知道编译器会发生什么,你可以反汇编目标代码。表示指针的值可能已经存储在堆栈中,并且会在int返回时收到指针(指针本身,而不是指向的main)。

答案 2 :(得分:0)

没有。指针不是共享指针,默认情况下不会在C ++中自动删除。

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