c++删除指针本身,而不是删除指向数据的指针

C++ deleting a pointer itself instead of deleting the pointed-to-data

本文关键字:指针 删除 数据 c++      更新时间:2023-10-16

我从阅读parashift.com得知在指针上使用delete会释放内存

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

pointed-to-data。

关键字应该是delete_the_thing_pointed_to_by。相同的当释放a所指向的内存时,就会发生英语滥用C语言中的指针:free(p)实际上是指free_the_stuff_pointed_to_by(p)。

和维基文章"delete (c++)"说"许多程序员设置指针为NULL之后,以尽量减少编程错误"

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

声明的指针仍然占用内存,这是正确的吗?

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

如何删除指针?

通常该指针将在作用域结束时停止存在。

的例子:

{
  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

…这可以作为递归示例的起点。


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

  • http://en.cppreference.com/w/cpp/language/storage_duration
  • http://en.cppreference.com/w/cpp/language/static

请注意,任何变量(包括指针)都占用一定数量的内存,这与它的存储时间无关。通常,如果同时为太多对象分配空间,就会耗尽内存。因此,您应该避免实现无限递归、分叉炸弹、内存泄漏或类似的东西。

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

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

声明的指针仍然占用内存,这是正确的吗?

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

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

  • 当然会占用内存,billions * sizeof(void*)。需要删除指针与它是否占用空间无关,所有都占用空间(好吧,几乎,有一些特殊的优化);您只需要将delete分配给new

如何删除指针?

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

1)通常指针位于堆栈上或者是另一个类的成员,您不需要担心删除这样的指针。

2)是的。

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

4)要么让局部指针超出作用域,要么删除包含它的对象。

最后请注意,原始指针是非常不受欢迎的。建议使用合适的容器,如vector,或者根据需要使用合适的智能指针。

声明的指针占用堆栈上的内存,当它超出作用域时将被删除。这与处理基本类型的过程相同。你不需要担心堆栈上任何东西的内存管理。

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

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

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

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

应该删除p所指向的内存(当它有意义时),但是p只是一个auto变量,它将被"删除"。

声明的指针仍然占用内存,这是正确的吗?

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

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

如何删除指针?

,这取决于你是如何创建指针的。如果您出于某种原因将其分配到堆上,那么您也应该释放该内存。

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

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

使其成为指针的唯一事实是,存储在该变量中的值恰好是内存中某个位置的地址。当你在指针上调用delete时,你释放的是存储在指针地址上的内存,而不是指针变量本身所使用的内存。

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

{
  int *p = NULL;
}

右括号后销毁指针

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

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