【问题标题】:C++ deleting a pointer itself instead of deleting the pointed-to-dataC ++删除指针本身而不是删除指向的数据
【发布时间】:2011-11-14 20:57:24
【问题描述】:

我通过阅读 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++)”的 wiki 文章说“许多程序员事后将指针设置为 NULL 以尽量减少编程错误”

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

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

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

如何删除指针?

【问题讨论】:

  • 指针本身通常是在堆栈上分配的(除非在处理指向指针的指针等时...)。当弹出包含它的堆栈帧时,它会从堆栈中删除。您将如何手动删除它?
  • 这是一个很好的面试问题。
  • 只调用删除你用new创建的东西。你的指针指向的对象是用 new 创建的,所以在它上面调用 delete。但是指针呢? (它是用新创建的吗(与它所指向的区别))。
  • 为了学习-你将如何创建一个新的指针?我无法绕过它
  • right.. 但是 int* 将是一个对象.. 然后我的问题将是 ptr-to-ptr pp.. 我现在知道它会超出范围并被自动删除。

标签: c++ delete-operator


【解决方案1】:

通常指针会在作用域的末尾停止存在。

例子:

{
  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

同样,指针变量本身将在作用域结束时被销毁,因为它具有自动存储持续时间。 相比之下,我们使用new 运算符分配的int 对象(在此示例中指向该对象)具有动态存储持续时间。它将继续驻留在内存中,直到调用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

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


注意有一个东西叫做static storage duration,这意味着变量会一直存在到程序结束(例如,全局变量或静态变量)。如果您想了解有关此主题的更多信息,请参阅:


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

【讨论】:

  • 我认为这个答案应该作为一个很好的例子包含在 delete(C++) wiki 中。谢谢!
【解决方案2】:

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

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

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

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

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

  • 当然会用完内存,billions * sizeof(void*)。需要删除指针与是否占用空间无关,everything 占用空间(嗯,差不多,有一些特殊的优化);你只需要deletenew分配的内容。

如何删除指针?

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

【讨论】:

  • 最后一条语句的示例可能是:int **a = new int*;,它是一个指向动态分配的 int 指针的指针。
【解决方案3】:

1) 通常一个指针在堆栈上或另一个类的成员,你不必担心删除这样的指针。

2) 是的。

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

4) 要么让本地指针超出范围,要么删除包含它的任何对象。

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

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

    • int x; return &amp;x;... 你仍然需要担心堆栈上分配的一些东西的内存管理。
    【解决方案5】:

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

    这取决于指针是如何创建的。如果你在堆栈上创建一个指针:

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

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

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

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

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

    如何删除指针?

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

    【讨论】:

      【解决方案6】:

      指针只是一个变量,就像一个int。在 32 位 CPU 上,一个指针将消耗 4 个字节的存储空间,而在 64 位系统上则为 8 个字节。

      所以如果你声明了十亿个指向 NULL 的指针,你实际上已经声明了十亿个 *int*s。

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

      【讨论】:

        【解决方案7】:

        您不能删除指针本身 - 只能删除它所指向的数据。
        指针在其作用域结束时被销毁:

        {
          int *p = NULL;
        }
        

        右括号后指针被破坏

        【讨论】:

          【解决方案8】:

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

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

          【讨论】:

            猜你喜欢
            • 2019-03-31
            • 2010-09-08
            • 2015-08-09
            • 1970-01-01
            • 2013-09-09
            • 2011-02-18
            • 2013-03-31
            • 1970-01-01
            • 2020-07-13
            相关资源
            最近更新 更多