C++删除指针自身而不是删除所指向的数据

3

我从parashift.com上了解到,使用delete释放指针所指向的内存。

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

指向的数据。

关键字实际上应该是delete_the_thing_pointed_to_by。在C中释放指针所指向的内存时,同样滥用英语:free(p)实际上意味着free_the_stuff_pointed_to_by(p)。

wiki上的“delete (C++)”文章说,“许多程序员在最小化编程错误方面设置指针为NULL后会使用delete”。

需要考虑删除指针本身吗?

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

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

如何删除指针?


2
指针本身通常在堆栈上分配(除非涉及到指向指针等情况)。当包含它的堆栈帧弹出时,它将从堆栈中删除。你如何手动删除它呢? - user142019
这是一个不错的面试问题。 - Danra
1
只有调用使用new创建的对象时才需要使用delete。你的指针所指向的对象是使用new创建的,因此需要对其调用delete。但是指针本身呢?(它是使用new创建的吗(与它所指向的对象区分开来))。 - Martin York
为了学习,你会如何使用new创建一个指针?我无法理解。 - PPTim
没错,但是int*将会是一个对象。那么我的问题就会出现在指向指针pp上。我现在知道它会超出作用域并自动删除。 - PPTim
8个回答

15
通常指针会在作用域结束时停止存在。
示例:
{
  int *p = NULL;
  // do something with p
} // <-- p will be destroyed here

指针变量被称为具有“自动存储持续时间”。如果一贯地将 0, NULL, 或 nullptr 赋值给指向指定类型对象之外的指针变量,则可以轻松识别指针是否安全进行解引用。这种做法与指针的生命周期或先前指向的对象(如果有)没有直接关系。


相比之下,当您拥有以下代码:

{
  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

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


请注意,存在一种称为静态存储持续时间的东西,这意味着变量将存在直到程序结束(例如全局或静态变量)。如果您想了解更多关于此主题的知识,请参见:


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


我认为这个答案应该被包括在delete(C++)维基中作为一个优秀的例子。谢谢! - PPTim

7

需要考虑删除指针本身吗?

  • 只有在指针本身没有自动内存管理时才需要考虑。也就是说,如果使用newmalloc为指针本身分配了存储空间,则需要考虑删除指针本身。

声明指针仍然占用内存,这种说法正确吗?

  • 指针会占用内存,因为它必须存储在某个位置以便使用,对吧?

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

  • 当然会占用内存,billions * sizeof(void*)。需要删除指针与它是否占用空间无关,每个东西都会占用空间(几乎是这样的,有一些特殊的优化);你只需要delete使用new分配的内容。

如何删除指针?

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

最后一条语句的一个示例可以是:int **a = new int*;,这是一个指向动态分配的int指针的指针。 - user142019

3

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

2) 是的。

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

4) 要么让本地指针超出作用域,要么摆脱包含它的任何对象。

最后请注意,原始指针相当不受欢迎。更喜欢适当的容器,例如 vector,或者根据需要选择适当的智能指针。


1

一个声明的指针占用堆栈上的内存,并且在超出其作用域时将被删除。这与原始类型发生的过程相同。您无需担心堆栈上的任何内容的内存管理。

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


1
int x; 返回 &x; ... 对于在堆栈上分配的某些东西,您仍然需要担心内存管理。 - Thomas Eding

1
需要考虑删除指针本身吗?
这取决于指针的创建方式。如果您在堆栈上创建指针:
 void func(void) {
     int* p;
     ...
 }

你应该删除指向p的内存(在合适的时候),但是p只是一个auto变量,当堆栈被解开时它会被“删除”;

声明的指针仍然占用内存吗?

也就是说,如果我声明了数十亿个不同的指针并将它们设置为NULL,它们仍然会占用内存(因此我需要删除指针本身)。

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

如何删除指针?

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


0

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

因此,如果您声明了十亿个指向NULL的指针,您实际上已经声明了十亿个*int*。

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


0

您无法删除指针本身 - 仅删除其指向的数据。
当指针的作用域结束时,指针将被销毁:

{
  int *p = NULL;
}
闭括号后指针被销毁

-1
问题是什么是删除指针。如果您将新指针分配给相同的变量,则无需担心删除数十亿个指针。如果您为指针分配空间,则肯定应该删除它们,但再次,它将是指向指针的指针,因此被删除的是指针,而不是指针本身。如果您静态地分配空间(例如声明数十亿个指针的数组),则无法真正删除它。

简而言之,我认为您需要更好地了解指针的性质。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接