我记得在某个地方读到过,在C++中,delete NULL
是必须是一个有效的操作,但我不记得为什么它应该是这样的。请问有人能够提醒我吗?
我记得在某个地方读到过,在C++中,delete NULL
是必须是一个有效的操作,但我不记得为什么它应该是这样的。请问有人能够提醒我吗?
确切原因:
可能的推理:
delete
之前检查每个指针是否为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个字符(至少)吗?
delete n
,是吧? :D - Ed S.0
是一个有效的内存地址? - stijn0
。NULL
是在C语言中被定义为0
的宏。该语言本身用空指针及其语义来表达。 在实践中,它们通常是相同的,但不一定如此。我必须检查标准:D - Ed S.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
内部执行它是更简单的解决方案。恩,我清楚地记得删除指向const
的指针(现在可以)的规则随着标准化发生了变化,即它们在ARM、注释参考手册中是不同的。
但是我不确定删除0;我认为它一直被支持。
无论如何,这只涉及到方便,对于一个成本检查微不足道的操作,而且编译器可能比某些用户定义的删除包装函数更有效地完成。
delete NULL
抛出异常呢?或者更糟糕的是,如果标准未定义并且在不同编译器之间存在不一致的行为,那该怎么办呢? - Ben Cottrell