在删除具有重载删除的对象之前进行NULL检查

Alo*_*ave 26 c++ null delete-operator

这是代码审查评论之一.

在为任何对象调用delete之前检查NULL是个好主意吗?

我确实理解删除运算符在内部检查NULL并且是多余的,但是提出的参数是删除,因为运算符可以重载,如果重载版本没有检查NULL,它可能会崩溃.因此,假设如果和何时删除将被重载,它是否安全合理,它将检查是否为NULL?在我的理解中,合理地假设第一种情况是重载删除应该处理NULL检查,并且审查点不成立.你怎么看?

ybu*_*ill 35

不,不要检查null.标准说这delete (T*)0;是有效的.它只会使您的代码复杂化,没有任何好处.如果operator delete重载,最好在运算符的实现中检查null.只需保存代码行和错误.

编辑:这个答案被接受和赞成,但在我看来,它的信息量不大.这里的所有答案中都有一个缺失的部分,为了良心,让我在这里添加最后一部分.

该标准实际上在[basic.stc.dynamic]中说,至少从C++ 03开始:

C++程序中定义的任何分配和/或释放函数,包括库中的缺省版本,都应符合3.7.4.1和3.7.4.2中规定的语义.

引用的部分以及其他答案中列出的标准中的其他一些部分,表示传递空指针的语义是无操作.

  • @David:请完整阅读ybungalobill的评论---如果它没有调用UB,它就可以符合.例如:放置`delete`对其参数(根本没有)做任何事情,因此,它也不需要检查null. (3认同)
  • @David:是的,我并不打算自己做一个删除`删除',而是用它作为"必须检查null或不符合"语句的反例. (3认同)
  • @Naveen @Als:在弱势下是的.没有强烈的"符合"一词.如果你实现不检查NULL的操作符删除它仍然符合(例如它只打印`cout << address <<'\n'`).但如果它带来了未定义的行为,那么你的`operator delete`实现就会出现错误. (2认同)
  • @David:所以,使用自定义`new`运算符,您可以(并且应该)定义相应的自定义`delete`运算符,这样,如果对象的构造失败,则可以释放已分配的内存.放置`delete`对应于放置`new`(当然,除了返回给定的指针之外,它什么都不做). (2认同)
  • @David:正如@ybungalobill所说,检查NULL不需要不触发UB.因此,检查NULL不需要符合要求,所需要的只是它与NULL一起使用. (2认同)

Oli*_*rth 19

我会说,这更有理由确保如果你超载operator delete,那么你应该总是检查它NULL,否则你就会破坏语义.


Pra*_*rav 7

在为任何对象调用delete之前检查NULL是个好主意吗?

没有!

int *p = NULL;
delete p ; //no effect
Run Code Online (Sandbox Code Playgroud)

标准说[第5.3.5/2节]

如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针类型,并使用转换后的操作数代替本节其余部分的原始操作数.在任一替代方案中,如果delete的操作数的值是空指针,则操作无效.

在节中 18.4.1.1/13

void operator delete(void* ptr) throw();

void operator delete(void* ptr, const std::nothrow_t&) throw();

默认行为:

- 对于ptr的空值,什么都不做.

- ptr的任何其他值应该是先前通过调用默认运算符new返回的值,该值不会被对operator delete(void*)的干预调用无效(17.4.3.7).对于ptr的这种非空值,回收先前调用默认运算符new分配的存储.

编辑:

詹姆斯坎泽在这里

它仍然是操作员删除(或删除[])的响应性检查; 标准不保证不会给出空指针; 如果给出空指针,标准要求它是无操作.或者允许实现调用它.根据最新的草案,"提供给释放函数的第一个参数的值可能是空指针值;如果是,如果解除分配函数是标准库中提供的函数,则调用无效." 我不太确定"标准库中提供的那个"的含义是什么意思 - 从字面上看,因为他的功能不是标准库提供的,句子似乎不适用.但不知何故,这没有意义.

  • @wihelmtell:不,我在阅读问题标题后没有停止.这就是为什么我把`bytes.com`线程联系起来并让他读詹姆斯坎泽的回答. (6认同)
  • @wilhelmtell:难道你不能看到****** (2认同)

jal*_*alf 6

我会说,超载的责任delete就像你期望的那样delete.也就是说,它应该将 NULL指针作为无操作处理.

因此,调用一个重载的删除时,你应该检查NULL.您应该依赖重载删除才能正确实现.