为什么不删除将指针设置为NULL?


127

我一直想知道为什么删除后将指针自动设置为NULL 并不是标准的一部分。如果得到解决,那么由于无效指针而导致的许多崩溃将不会发生。但话虽如此,我仍然可以想到该标准限制了这一点的几个原因:

  1. 性能:

    附加说明可能会降低delete性能。

  2. 可能是因为const指针。

    然后我想标准再次可以为这种特殊情况做些什么。

有谁知道不允许这样做的确切原因?

Answers:


150

Stroustrup自己回答。摘录:

C ++明确允许delete的实现将左值操作数清零,我曾希望实现能够做到这一点,但是这种想法似乎在实现者中并不流行。

但是他提出的主要问题是delete的参数不必是左值。


我认为这可以使用更多解释。我什至不知道他在说什么...我想我必须稍后再回来,直到我能花几个小时研究这个问题,直到我明白为止。或者,您可以详细说明答案,以帮助我们更快地理解。
加布里埃尔·斯台普斯

63

首先,设置为null将需要内存存储的变量。的确,您通常在变量中有一个指针,但有时您可能想删除一个刚计算出的地址处的对象。使用“无效”删除将是不可能的。

然后是性能。您可能以这样的方式编写代码:删除完成后,指针将立即超出范围。用null填充只是浪费时间。C ++是一种具有“不需要它?然后您不必为此付出代价”的思想的语言。

如果您需要安全保护,可以使用各种各样的智能指针,也可以编写自己的更好,更智能的指针。


4
即使您不经常看到该地址,它仍然可以计算出地址的好点
snemarch

当您说有时您可能想删除刚刚计算出的地址处的对象时,是在谈论新的位置。???
毁灭者

@PravasiMeet不,我的意思是delete (ptr + i)
Sharptooth

39

您可以有多个指向该内存的指针。如果您为删除指定的指针设置为null,但所有其他指针都不设置为null,则会产生错误的安全感。指针不过是一个地址,一个数字。也可能是带有取消引用操作的int。我的观点是,您还必须扫描每个指针,以找到那些引用了刚刚删除的相同内存的指针,并将它们也清空了。扫描所有指针以查找该地址并将其清空将是计算密集型的,因为该语言不是为此目的而设计的。(尽管其他一些语言构造了它们的引用,以不同的方式实现相似的目标。)


19

指针可以保存在多个变量中,将其中一个设置为NULL仍会将无效的指针保留在其他变量中。因此,您获得的收益并不多,您很有可能会产生一种错误的安全感。

除此之外,您还可以创建自己的函数来实现所需的功能:

template<typename T>
void deleten(T *&ptr) {
  delete ptr;
  ptr = NULL;
}

12

因为实际上并不需要,并且因为需要删除而采用指针对指针,而不仅仅是指针。


确实如此,但这会导致相同的开销
09年

7

delete通常在析构函数中使用,在这种情况下,将成员设置为NULL是没有意义的。几行之后,在结束时},该成员不再存在。在赋值运算符中,无论如何通常都会在删除之后添加一个赋值。

而且,这将使以下代码非法:

T* const foo = new T;
delete foo;

6

这是另一个原因。假设delete确实将其参数设置为NULL:

int *foo = new int;
int *bar = foo;
delete foo;

应该将bar设置为NULL吗?你能概括一下吗?


5

如果您有一个指针数组,并且第二个操作是删除空数组,那么在要释放内存时,将每个值设置为null是没有意义的。如果您希望它为null ..则将null写入:)


4

C ++允许您定义自己的运算符new和delete,以便例如它们将使用您自己的池分配器。如果这样做,则可以使用new和delete来处理严格意义上不是地址而是在池数组中声明索引的内容。在这种情况下,NULL(0)的值可能具有法律含义(指池中的第一项)。
因此,将delete自动设置为NULL并不总是具有-将值设置为无效值的含义。无效值可能并不总是NULL。


4

C ++的理念是“只有在使用时才付费”。我认为它可以回答您的问题。

同样,有时您可能拥有自己的堆,该堆将恢复已删除的内存..或者有时指针不属于任何变量。或将指针存储在几个变量中-仅将其中一个变量设为零即可。
如您所见,它有很多问题和可能的问题。


3

自动将指针设置为NULL不能解决大多数错误使用指针的问题。它可以避免的唯一崩溃是如果您尝试将其删除两次。如果在这样的指针上调用成员函数怎么办?它仍然会崩溃(假设它访问成员变量)。C ++不会限制您在NULL指针上调用任何函数,也不应该从性能的角度执行此操作。


-1

我看到人们对此问题给出了奇怪的答案。

ptr = NULL; 这样一个简单的语句如何导致性能延迟?

另一个答案是说我们可以有多个指向同一内存位置的指针。当然可以。在这种情况下,对一个指针的删除操作将仅使该指针为NULL(如果delete使指针为NULL),而另一个指针将为非NULL,并指向可用的内存位置。

解决方案应该是用户应该删除所有指向相同位置的指针。在内部,它应该检查内存是否已经释放或不释放。仅使指针为NULL。

Stroustrup本可以设计删除以这种方式工作。他认为程序员会照顾这一点。所以他无视。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.