使用重载删除删除对象之前进行 NULL 检查

发布于 2024-09-25 12:56:02 字数 222 浏览 1 评论 0原文

这是代码审查评论之一。

在调用任何对象的删除之前检查 NULL 是个好主意吗?

我确实理解删除运算符在内部检查 NULL 并且是多余的,但提出的论点是删除,因为运算符可以重载,如果重载版本不检查 NULL 它可能会崩溃。那么,假设如果以及何时删除将被重载,它会检查 NULL 是否安全合理? 根据我的理解,假设第一种情况是合理的,即重载删除应负责 NULL 检查,并且审查点并不成立。你怎么认为?

This came up as one of the code review comments.

Is it a good idea to check for NULL before calling delete for any object?

I do understand delete operator checks for NULL internally and is redundant but the argument put forth was delete as an operator can be overloaded and if the overloaded version doesn't check for the NULL it may crash. So is it safe and reasonable to assume that if and when delete will be overloaded it will check for the NULL or not?
In my understanding its reasonable to assume the first case that overloaded delete shall take care of the NULL check, and the review point doesn't hold good. What do you think?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

⊕婉儿 2024-10-02 12:56:02

不,不要检查 null。标准规定 delete (T*)0; 是有效的。它只会使你的代码变得复杂而没有任何好处。如果operator delete 重载,最好在操作符的实现中检查 null 。只是保存代码行和错误。

编辑:这个答案被接受并投票,但在我看来,它的信息量不是很大。这里的所有答案都缺少一个部分,为了良心,让我在这里添加最后一个部分。

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

C++ 程序中定义的任何分配和/或释放函数(包括库中的默认版本)应符合 3.7.4.1 和 3.7.4.2 中指定的语义。

引用的部分以及其他答案中列出的标准中的其他一些地方都说传递空指针的语义是无操作。

No, don't check for null. The standard says that delete (T*)0; is valid. It will just complicate your code for no benefits. If operator delete is overloaded it's better to check for null in the implementation of the operator. Just saves code lines and bugs.

EDIT: This answer was accepted and upvoted, yet, in my opinion, it was not very informative. There is one missing piece in all answers here, and, for conscience sake, let me add this last piece here.

The standard actually says in [basic.stc.dynamic], at least since C++03:

Any allocation and/or deallocation functions defined in a C++ program, including the default versions in the library, shall conform to the semantics specified in 3.7.4.1 and 3.7.4.2.

Where the referenced sections, as well as some other places in the standard listed in other answers, say that the semantics of passing a null pointer are a no-op.

别再吹冷风 2024-10-02 12:56:02

我想说,这更多是确保如果您重载operator delete,那么您应该始终让它检查NULL,否则您就会破坏语义。

I would say that that's more a reason to ensure that if you overload operator delete, then you should always have it check for NULL, otherwise you're breaking the semantics.

別甾虛僞 2024-10-02 12:56:02

在调用任何对象的删除之前检查 NULL 是个好主意吗?

不!

int *p = NULL;
delete p ; //no effect

标准规定[第 5.3.5/2 节]

如果操作数是类类型,则通过调用上述转换函数将操作数转换为指针类型,并在本节的其余部分中使用转换后的操作数代替原始操作数。无论哪种选择,如果删除操作数的值为空指针,则该操作无效

此外,在 18.4.1.1/13 节中

voidoperatordelete(void*ptr) throw();

voidoperatordelete(void*ptr, const std::nothrow_t& ;) 抛出();

默认行为:

对于 ptr 的 null 值,不执行任何操作

— ptr 的任何其他值应是先前通过调用默认运算符 new 返回的值,该值不会因对运算符 delete(void*) 的干预调用而失效 (17.4.3.7)。对于此类非空 ptr 值,回收先前调用默认运算符 new 分配的存储空间。

编辑

James Kanze 此处 说的是

仍然是操作员delete(或delete[])的责任来检查;该标准不保证它不会被赋予空指针;该标准要求如果给定空指针则它是无操作的。或者允许实现调用它。根据最新草案,“提供给释放函数的第一个参数的值可能是空指针值;如果是这样,并且释放函数是标准库中提供的,则调用无效。”我不太确定“标准库中提供的函数”的含义是什么——从字面上看,因为他的函数不是标准库提供的函数,所以这句话似乎不适用。但不知何故,这没有意义。

Is it a good idea to check for NULL before calling delete for any object?

No!

int *p = NULL;
delete p ; //no effect

The Standard says [Section 5.3.5/2]

If the operand has a class type, the operand is converted to a pointer type by calling the above-mentioned conversion function, and the converted operand is used in place of the original operand for the remainder of this section. In either alternative, if the value of the operand of delete is the null pointer the operation has no effect.

Furthermore in Section 18.4.1.1/13

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

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

Default behavior:

For a null value of ptr, do nothing.

— Any other value of ptr shall be a value returned earlier by a call to the default operator new, which was not invalidated by an intervening call to operator delete(void*) (17.4.3.7). For such a non-null value of ptr, reclaims storage allocated by the earlier call to the default operator new.

EDIT :

James Kanze here says that

It's still the responisiblity of operator delete (or delete[]) to check; the standard doesn't guarantee that it won't be given a null pointer; the standard requires that it be a no-op if given a null pointer. Or that the implementation is allowed to call it. According to the latest draft, "The value of the first argument supplied to a deallocation function may be a null pointer value; if so, and if the deallocation function is one supplied in the standard library, the call has no effect." I'm not quite sure what the implications of that "is one supplied in the standard library" are meant to be---taken literally, since his function is not one provided by the standard library, the sentence wouldn't seem to apply. But somehow, that doesn't make sense.

回忆凄美了谁 2024-10-02 12:56:02

我想说,重载的 delete 有责任像您期望的 delete 那样行事。也就是说,它应该将NULL指针作为无操作来处理。

因此,当调用重载删除时,您不应该检查 NULL。您应该依靠重载删除来正确实现。

I would say it is the responsibility of an overloaded delete to behave like you expect delete to behave. That is, it should handle NULL pointers as a no-op.

And so, when calling an overloaded delete, you should not check for NULL. You should rely on the overloaded delete to be implemented correctly.

宁愿没拥抱 2024-10-02 12:56:02

无需检查 null。删除运算符会检查 null,因此不需要额外的检查。

No need to check null. delete operator does chck for null so additional check is not required.

叹倦 2024-10-02 12:56:02

delete (T*)0; 有效且不执行任何操作,同样 free(NULL); 也是有效且不执行任何操作。如果重载 delete 运算符,您的实现应该具有相同的语义。该标准说明了标准delete 将如何工作,但我不认为它说明了重载的delete 应该如何表现。为了与标准/默认行为保持一致,它应该允许 (T*)0 作为输入。

delete (T*)0; is valid and does nothing, similarly free(NULL); is also valid and does nothing. If you overload the delete operator, your implementation should carry the same semantics. The standard says how the standard delete will work, but I don't think it says how an overloaded delete should behave. For the sake of consistency with the standard/default behaviour, it should allow (T*)0 as input.

心的憧憬 2024-10-02 12:56:02

来自标准文档,18.5.1.1.13 下的 delete

默认行为:如果 ptr 为 null,则不执行任何操作。否则,回收先前调用分配的存储空间
新运算符。

因此,您不必默认检查..

From Standard docs, 18.5.1.1.13 under delete,

Default behavior: If ptr is null, does nothing. Otherwise, reclaims the storage allocated by the earlier call to
operator new.

So, you don't have to check by default..

三生殊途 2024-10-02 12:56:02

删除之前无需检查 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.
}

No need to check for NULL prior to deleting. If someone has overloading delete with something that does not behave in a standard way then that's the real problem. No-one should take lightly the task of overloading delete and should always support expected behaviour such as checking for NULL and taking no action.

However, for what it's worth, you should always remember to assign zero to any pointer that you've just deleted, unless for example you are about to delete the pointer as well:

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.
}
守不住的情 2024-10-02 12:56:02

是否不需要需要检查。如果任何人超载了该方法,他就有责任对 NULL 进行处理。

Is it not necesary to check. If anyone overload the pethod, is his responsibility to to whatever with NULL.

走过海棠暮 2024-10-02 12:56:02

我想说这些问题包含不完整的信息。我的商店在我们的编码标准中仍然在删除之前检查 NULL,因为我们仍然有一个必须支持的编译器/平台配置,如果传递 NULL,它就会进入默认删除运算符的未定义行为。如果原发帖者有类似的情况,那么就需要检查 NULL,否则,请更改编码标准!

I would say the questions contains incomplete information. My shop still has a check for NULL before delete in our coding standard, as we still have one compiler/platform configuration that we must support that goes into undefined behavior with the defualt delete operator if it is passed NULL. If the original poster has a simular situation then there is a point to the check for NULL, otherwise, change the coding standard!

一影成城 2024-10-02 12:56:02

一点 C++ 的迂腐:
NULL 不是一个内置的概念。是的,我们都知道这意味着什么,但在 C++0X 之前的 C++ 中,空指针概念只是值 0。NULL 通常是扩展为 0 的特定于平台的宏。

在 C++0X 中,我们得到 nullptr,它是比普通的零更清晰,并且不能转换为除 bool 之外的任何整数类型,并且是比 NULL 更好的概念(或者可能是 NULL 背后概念的更好实现)。

A bit of C++ pedantry:
NULL is not a built-in concept. Yes we all know what it means but in C++ before C++0X the null pointer concept is simply the value 0. NULL is usually a platform-specific macro that expands to 0.

With C++0X we're getting nullptr which is clearer than a plain zero and is not convertible to any integral type except bool, and is a better concept than NULL (or perhaps a better implementation of the concept behind NULL).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文