8

我记得在某处读到它是delete NULLC++ 中的有效操作所必需的,但我不记得为什么它应该如此。有人可以提醒我吗?

4

7 回答 7

14

确切原因:

  • 因为 C++ 标准委员会是这样决定的。

可能的推理:

  • delete因为在调用用户代码之前检查每个指针是否为 NULL 会导致太多的代码膨胀。
于 2012-09-22T06:24:52.520 回答
11

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

此规则简化了对指针可能为空的故障案例和其他实例的管理。这是一种简单、廉价的检查方式,并且为语言增加了明显的便利性。

例如,如果存在许多会导致动态内存分配的条件,但也存在其他不会导致动态内存分配的条件,则可以方便地delete在末尾粘贴 a 而不用担心它。

// 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)

......那将是蹩脚的。既然这将是规范,一个本质上是强制性的约定,为什么不完全消除检查的需要呢?为什么每次调用都需要额外的 5 个字符(最少)delete

于 2012-09-22T06:25:52.383 回答
3

首先,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 检查,这会使代码的可读性大大降低,并使代码的逻辑变得模糊。

于 2012-09-22T08:07:27.900 回答
2

因为标准委员会知道没有程序可以让 NULL 指向一个有效的对象,即 NULL 不能指向一个有效的内存,所以写是安全的,正是delete NULL因为它实际上并没有删除任何东西。既然这是安全的,那么它可以让您无需在之前检查 NULL delete

//if (ptr != NULL) NOT NEEDED
   delete ptr; //safe even if ptr == NULL
于 2012-09-22T06:30:37.950 回答
2

因为库实现者只需编写if (ptr == nullptr) return;一次。作为用户,您必须在整个程序中编写 9999999999 次。因此,这是一个简单的案例,在内部delete进行操作要简单得多。

于 2012-09-22T08:09:47.540 回答
1

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

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

于 2012-09-22T06:24:52.870 回答
0

好吧,我确实清楚地记得删除指针的规则const(现在可以)随着标准化而改变,即它们在 ARM 注释参考手册中有所不同。

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

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

于 2012-09-22T07:34:14.517 回答