为什么 delete 不将指针设置为 NULL?

我一直想知道为什么在 删除之后自动设置指针为 NULL 不是标准的一部分。如果这个问题得到解决,那么由于无效指针引起的许多崩溃就不会发生。不过,话虽如此,我还是可以想出几个标准限制这种做法的理由:

  1. 演出:

    额外的指令可能会降低 delete的性能。

  2. 会不会是因为 const指针。

    那么,我想,标准公司可以为这个特殊情况做些什么。

有人知道不允许的确切原因吗?

62164 次浏览

因为实际上没有任何需要,而且因为这将需要删除采取指针到指针,而不仅仅是指针。

如果您有一个指针数组,并且您的第二个操作是删除空数组,那么当内存即将被释放时,没有必要将每个值设置为 null。如果你想让它为空。.写空:)

首先,设置为 null 将需要一个内存存储变量。的确,通常在变量中有一个指针,但有时可能希望 删除是一个刚刚计算好的地址。这是不可能的“无效”删除。

然后是表演。您可能以这样的方式编写代码,即在完成 删除之后,指针将立即超出作用域。用空填充只是浪费时间。C + + 是一种带有“不需要它?”?那么你就不必为此付出代价”的意识形态。

如果你需要安全,有一个广泛的智能指针在您的服务或您可以自己编写-更好和更聪明。

可以有多个指向该内存的指针。如果您为删除操作指定的指针被设置为 null,而其他所有指针都没有被设置为 null,那么它将创建一种错误的安全感。指针只不过是一个地址,一个数字。它也可以是一个带有解引用操作的 int。我想说的是,你还必须扫描每一个指针,找到那些引用相同的内存,你刚刚删除,并取消它们。扫描这个地址的所有指针并将它们剔除,这将是计算量很大的工作,因为这种语言不是为此而设计的。(尽管其他一些语言以不同的方式构造它们的引用来实现类似的目标。)

一个指针可以保存在多个变量中,如果将其中一个设置为 NULL,那么其他变量中的指针仍然是无效的。所以你并没有真正获得多少,你更有可能创造一种错误的安全感。

除此之外,您还可以创建自己的函数来完成您想要的任务:

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

C + + 允许您定义自己的运算符 new 和 delete,例如,它们将使用您自己的池分配器。如果您这样做了,那么就可以在您的池数组中使用 new 和 delete,它们不是严格意义上的地址,而是索引。在此上下文中,NULL (0)的值可能具有法律意义(指的是池中的第一个项)。
因此,让 delete 自动将 NULL 设置为它的参数并不总是意味着-将值设置为无效值。无效值不一定总是 NULL。

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

C + + 的哲学是“只有使用了才能付费”,我想它可以回答你的问题。

有时你也可以拥有自己的堆来恢复被删除的内存。.或者有时指针不属于任何变量。或者存储在少数变量中的指针——可能只有其中一个为零。
正如你所看到的,它有许多问题和可能的问题。

delete主要用于析构函数,在这种情况下,将成员设置为 NULL 是没有意义的。几行之后,在关闭的 }处,该成员不再存在。在赋值运算符中,删除之后通常是赋值。

此外,它还会使以下代码成为非法代码:

T* const foo = new T;
delete foo;

这里还有另一个原因; 假设 delete 确实将其参数设置为 NULL:

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

应该将 bar 设置为 NULL 吗? 您能推广这个吗?

我见过有人对这个问题给出奇怪的答案。

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

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

解决方案应该是用户删除指向同一位置的所有指针。在内部,它应该检查内存是否已经释放,而不是不释放。只将指针设置为空。

Stroustrup 可以将 delete 设计成以这种方式工作。他认为程序员会解决这个问题。所以他无视了。