C ++删除指针本身而不是删除指向数据

时间:2011-11-14 20:57:24

标签: c++ delete-operator

我从阅读parashift.com了解到,在指针上使用delete会释放内存

  

[16.1] delete p是删除指针p还是指向数据* p?

     

指向数据。

     

关键字应该是delete_the_thing_pointed_to_by。相同   在释放a所指向的记忆时会发生滥用英语的行为   C中的指针:free(p)实际上意味着free_the_stuff_pointed_to_by(p)。

关于“删除(C ++)”的维基文章说“许多程序员事后将指针设置为NULL以最小化编程错误”

是否有必要考虑删除指针本身?

说声明的指针仍占用内存是否正确?

即。如果我要将数十亿个不同的指针声明为NULL,它仍会耗尽内存(因此我需要删除指针本身)。

如何删除指针?

8 个答案:

答案 0 :(得分:14)

通常指针会在范围的末尾停止存在。

示例:

{
  int *p = NULL;
  // do something with p
} // <-- p will be destroyed here

因此,指针变量具有自动存储持续时间。如果一致地完成,则将0NULLnullptr分配给不指向指定类型的对象的指针变量具有以下优点:可以轻松识别是否或取消引用指针是不安全的。这种做法与指针的生命周期或先前指向的对象(如果有)没有直接联系。


相反,如果您有以下代码:

{
  int *p = new int;
  // do something with p
  //delete p; // <-- the object p points to will not be destroyed unless it's deleted
} // <-- p will be destroyed here

同样,指针变量本身将在作用域的末尾被销毁,因为它具有自动存储持续时间。 相反,我们使用int运算符分配的new对象(在此示例中指针指向该对象)具有动态存储持续时间。它将继续驻留在内存中,直到调用delete来释放它。这可能会导致内存泄漏(如果您丢失对指向的对象p的任何引用,如本例所示)。


当然,如果指针是由它自己动态创建的,例如,如

{
  int** p = new int*;
  // do something with p
  //delete p; // <-- the object p points to will not be destroyed unless it's deleted
} // <-- p will be destroyed here

......这可能是递归示例的起点。


请注意,有一个名为静态存储持续时间的东西,这意味着该变量将存在直到程序结束(例如,全局变量或静态变量)。如果您想了解有关此主题的更多信息,请参阅:


请注意,与其存储持续时间无关,任何变量(包括指针)都会占用一定的内存量。通常,如果同时为太多对象分配空间,则内存不足。因此,你应该避免实现无限递归,fork炸弹,内存泄漏等相似的东西。

答案 1 :(得分:6)

  

是否有必要考虑删除指针本身?

  • 仅在指针本身没有自动内存管理时才需要。也就是说,如果指针本身的存储分配了newmalloc
  

说声明的指针仍占用内存是否正确?

  • 指针占用内存,必须存储在某个地方才能使用,对吧?
  

如果我要将数十亿个不同的指针声明为NULL,它仍会耗尽内存(因此我需要删除指针本身)。

  • 当然会耗尽内存billions * sizeof(void*)。需要删除指针与占用空间无关,一切占用空间(好吧,差不多,有一些特殊的优化);您只需delete new分配的内容。
  

如何删除指针?

  • 如何分配?如果它具有自动存储,那么当指针超出范围时,它的内存将自动释放。如果分配了new,则必须使用delete删除,new[] / delete[]malloc / free相同。

答案 2 :(得分:2)

1)通常指针位于堆栈或另一个类的成员上,您不必担心删除此类指针。

2)是的。

3)是的,他们会耗尽内存,你需要释放指针。

4)让局部指针超出范围,或者去除包含它的任何对象。

最后请注意,原始指针完全不受欢迎。首选适当的容器,如vector,或根据需要使用适当的智能指针。

答案 3 :(得分:1)

声明的指针占用堆栈上的内存,当它超出范围时将被删除。这与原始类型发生的过程相同。您无需担心堆栈中任何内容的内存管理。

另一方面,new运算符在堆上分配内存,必须使用delete显式删除。

答案 4 :(得分:1)

  

是否有必要考虑删除指针本身?

取决于指针的创建方式。如果你在堆栈上创建一个指针:

 void func(void) {
     int* p;
     ...
 }

你应该删除p指向的内存(当它有意义时),但是p只是一个auto变量,当堆栈展开时它将被“删除”;

  

说声明的指针仍占用内存是否正确?

     

即。如果我要将数十亿个不同的指针声明为NULL,它仍会耗尽内存(因此我需要删除指针本身)。

当然它确实...指针只是内存中包含虚拟内存地址的位置;实际上,将虚拟内存空间加倍会使指针占用的空间增加一倍(但不一定是它们指向的数据占用的空间)。

  

如何删除指针?

正如我所说,这取决于你如何创建指针。如果由于某种原因将它分配到堆上,那么你也应该释放内存。

答案 5 :(得分:0)

指针只是一个变量,如 int 。在32位CPU上,指针将占用4个字节的存储空间,在64位系统上占用8个字节。

因此,如果您向NULL声明了十亿个指针,那么您基本上已经宣布了十亿* int * s。

使它成为指针的事情只是存储在该变量中的值恰好是内存中某个地方的地址。当您在指针上调用 delete 时,您释放存储在指针中的地址,而不是指针变量本身使用的内存。

答案 6 :(得分:0)

您无法删除指针本身 - 仅指向数据 指针在其范围结束时被销毁:

{
  int *p = NULL;
}

关闭括号后,指针被解除

答案 7 :(得分:-1)

问题是删除指针是什么。如果为同一个变量分配新指针,则无需担心删除数十亿。如果你为指针分配空间,你肯定应该删除它们,但是它会再次指向指针,所以它是指针,而不是被删除的指针。如果你静态地分配空间(比如声明数十亿个指针的数组)你就不能真正删除它。

简而言之,我认为你需要更好地理解指针的本质。