为什么C++中允许删除空指针

Why is deleting null pointer allowed in C++

本文关键字:删除 空指针 许删除 C++ 为什么      更新时间:2023-10-16

我记得在某个地方读到delete NULL必须是C++中的有效操作,但我记不起为什么应该是这样了。有人能提醒我吗?

确切原因:

  • 因为C++标准委员会决定这么做

可能的推理:

  • 因为在用户代码中调用delete之前检查每个指针是否为NULL会导致代码膨胀

该规则不是严格必要的,因为如果没有它,语言就可以存在;这只是标准委员会做出的决定。空指针不是有效的内存地址。然而,我想相信,每一个决定都是有原因的,这些原因值得了解。

此规则简化了对故障情况和指针可能为null的其他实例的管理。这是一个简单、廉价的检查,它为语言增加了明显的便利性。

例如,如果存在许多会导致动态内存分配的条件,但也存在其他不会的条件,那么只需在末尾粘贴一个delete就可以了,而不用担心

// contrived example
void foo(int n) {
char *p = nullptr;
switch(n) {
case whatever:
case something_else:
p = new char[n];
break;
}
// some code...
delete [] p;  // look Ma, no check!
}

如果delete nullptr是非法的,那么对delete的每个调用都将被…包围

if(ptr)

那就太差劲了。既然这将是一种规范,一种基本上强制性的公约,为什么不完全消除检查的必要性呢?为什么每次调用delete都需要额外的5个字符(最少)?

首先,NULL从来都不是有效的指针值(在托管C++程序中),因此指针是否指向活动对象没有歧义。第二,内部内存管理逻辑无论如何都必须进行自己的检查才能记账,所以假设强制指针为非空不会带来任何好处。

因此,现在我们知道没有人反对这条规则,这里有一个对它有利的大论点:它使编写代码变得更容易。考虑一下这个简单的异常处理分配代码:

T * p1 = NULL;
T * p2 = NULL;
T * p3 = NULL;
try
{
p1 = new T;
p2 = new T;
p3 = new T;
}
catch (...)
{
delete p1;
delete p2;
delete p3;
throw;
}

这是简单而整洁的。如果我们需要在任何地方添加NULL检查,这将使代码的可读性大大降低,并模糊代码的逻辑。

因为标准委员会知道没有程序可以使用NULL来指向有效对象,即NULL不能指向有效内存,所以写delete NULL是安全的,确切地说,因为它实际上不会删除任何东西。既然这是安全的,那么它就不用在delete:之前检查NULL了

//if (ptr != NULL) NOT NEEDED
delete ptr; //safe even if ptr == NULL
因为库实现者只需要写一次if (ptr == nullptr) return;。作为用户,您必须在整个程序中写入9999999999次。因此,这是一个简单的情况,在delete内部进行操作要简单得多。

删除空指针无效(如果deallocation函数是标准库[2]中提供的函数),因此在调用delete之前不必检查空指针。

还检查删除NULL指针是否安全?它可能会帮助你

好吧,我清楚地记得,删除指向-const的指针的规则(现在可以了)随着标准化而发生了变化,也就是说,它们在ARM(带注释的参考手册)中有所不同。

但我不确定是否删除0;我认为它一直得到支持。

无论如何,这只是为了方便,对于一个检查成本微不足道的操作,并且编译器可能/可能比用户定义的删除包装函数更有效地完成检查。