这是代码审查评论之一。
在为任何对象调用delete之前检查NULL是否是个好主意?
我确实理解删除运算符在内部检查NULL并且是多余的,但是提出的参数是delete,因为运算符可能会重载,如果重载版本没有检查NULL,它可能会崩溃。因此,假设如果和何时删除将被重载,它是否安全合理,它将检查是否为NULL? 在我的理解中,合理地假设第一种情况是重载删除应该处理NULL检查,并且审查点不成立。你觉得怎么样?
答案 0 :(得分:35)
不,不要检查是否为空。标准说delete (T*)0;
有效。它只会使您的代码复杂化,没有任何好处。如果operator delete
被重载,最好在运算符的实现中检查null。只需保存代码行和错误。
编辑:这个答案被接受并投了赞成票,但在我看来,这个答案并不是很有用。这里所有答案中都有一个缺失的部分,为了良心,请允许我在这里添加最后一部分。
标准实际上在[basic.stc.dynamic]中说,至少从C ++ 03开始:
C ++程序中定义的任何分配和/或释放函数,包括库中的缺省版本,都应符合3.7.4.1和3.7.4.2中规定的语义。
引用的部分以及其他答案中列出的标准中的其他一些部分,表示传递空指针的语义是无操作。
答案 1 :(得分:19)
我想说这更有理由确保如果你重载operator delete
,那么你应该总是让它检查NULL
,否则你就会破坏语义。
答案 2 :(得分:7)
在为任何对象调用delete之前检查NULL是否是个好主意?
没有!
int *p = NULL;
delete p ; //no effect
标准说[第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分配的存储。
编辑:
James Kanze here说
仍然需要检查操作员删除(或删除[])的响应性;标准不保证不会给出空指针;如果给出空指针,标准要求它是无操作。或者允许实现调用它。根据最新的草案,“提供给释放函数的第一个参数的值可能是空指针值;如果是,如果解除分配函数是标准库中提供的函数,则调用无效。”我不太确定“标准库中提供的那个”的含义是什么意思 - 从字面上看,因为他的功能不是标准库提供的,句子似乎不适用。但不知何故,这没有任何意义。
答案 3 :(得分:6)
我认为重载delete
的责任就像您希望delete
的行为一样。也就是说,应将NULL指针作为无操作处理。
因此,在调用重载删除时,您应该不检查NULL。您应该依赖重载删除才能正确实现。
答案 4 :(得分:3)
无需检查null。 delete运算符会检查null,因此不需要进行额外的检查。
答案 5 :(得分:3)
delete (T*)0;
有效且无效,同样free(NULL);
也有效且无效。如果重载delete
运算符,则实现应该具有相同的语义。该标准说明了标准delete
的工作原理,但我认为它并未说明重载delete
应如何表现。为了与标准/默认行为保持一致,它应该允许(T*)0
作为输入。
答案 6 :(得分:3)
来自delete
下的标准文档 18.5.1.1.13 ,
默认行为:如果ptr为null,则不执行任何操作。否则,回收先前调用分配的存储空间 operator new。
因此,您不必默认检查 ..
答案 7 :(得分:2)
删除前无需检查NULL。如果有人因为标准方式不正常的事情而导致delete
超载,那么就是真正的问题。没有人应该轻视过载delete
的任务,并且应该始终支持预期的行为,例如检查NULL并且不采取任何行动。
然而,对于它的价值,你应该总是记住为你刚刚删除的任何指针指定零,除非你也要删除指针:
void MyObj::reset()
{
delete impl_;
impl_ = 0; // Needed here - impl_ may be reused / referenced.
}
MyObj::~MyObj()
{
delete impl_; // No need to assign here as impl_ is going out of scope.
}
答案 8 :(得分:2)
检查是否需要 。如果有人重载该方法,他有责任使用NULL。
答案 9 :(得分:1)
我会说这些问题包含不完整的信息。在我们的编码标准中,我的商店仍然在删除前检查NULL,因为我们仍然有一个编译器/平台配置,如果传递NULL,我们必须支持使用defualt delete操作符进入未定义的行为。如果原始海报有类似情况,那么检查是否有空,否则,改变编码标准!
答案 10 :(得分:0)
一些C ++迂腐: NULL不是内置概念。是的,我们都知道它意味着什么,但在C ++ 0X之前的C ++中,空指针概念只是值0. NULL通常是一个特定于平台的宏,它扩展为0。
使用C ++ 0X我们得到nullptr,它比普通零更清晰,并且不能转换为除bool之外的任何整数类型,并且是比NULL更好的概念(或者可能是NULL背后概念的更好实现)