删除空指针是否安全?
这是一种好的编码风格吗?
删除空指针是否安全?
这是一种好的编码风格吗?
delete
仍然会执行检查,因此在您的一侧进行检查会增加开销并且显得更加丑陋。一个非常好的实践是在delete
之后将指针设置为NULL(有助于避免双重删除和其他类似的内存破坏问题)。
如果delete
默认将参数设置为NULL,那就太好了。
#define my_delete(x) {delete x; x = NULL;}
(我知道R和L值是什么,但这样做不好吗?)
来自C++0x草案标准。
$5.3.5/2 - "[...]在任何一种情况下,delete运算符的操作数的值都可以是空指针值。[...]"
当然,没有人会对具有NULL值的指针执行'delete'操作,但这样做是安全的。理想情况下,应该避免编写删除NULL指针的代码。但是,在指针的删除(例如在容器中)发生循环时,有时候进行NULL指针值的删除是有用的。由于删除NULL指针值是安全的,因此可以真正编写不需要显式检查要删除的操作数是否为NULL的删除逻辑。
另外,C标准$7.20.3.2还指出,对NULL指针进行'free'操作不会执行任何操作。
free函数释放ptr指向的空间,即使其可以用于进一步的分配。如果ptr是空指针,则不执行任何操作。
NULL
的指针在至少一种情况下是完全合理的:当NULL
表示资源从未被分配(但可能已经被分配)并且外部约束(例如需要让C API拥有该资源)防止使用RAII时。 - BCS是的,它是安全的。
删除空指针是没有危害的,如果未分配的指针被初始化为零,然后仅仅被删除,在函数尾部往往会减少测试的次数。
由于前面的句子引起了混淆,这里提供一个例子,展示了描述内容的非异常安全写法:
void somefunc(void)
{
SomeType *pst = 0;
AnotherType *pat = 0;
…
pst = new SomeType;
…
if (…)
{
pat = new AnotherType[10];
…
}
if (…)
{
…code using pat sometimes…
}
delete[] pat;
delete pst;
}
这个示例代码可能有各种小问题,但我希望概念是清晰的。指针变量被初始化为零,这样在函数结尾处的delete
操作不需要在源代码中测试它们是否非空;库代码会执行该检查。
void func(void) { X *x1 = 0; Y *y1 = 0; … x1 = new[10] X; … y1 = new[10] Y; … delete[] y1; delete[] x1; }
。尽管代码中没有展示任何块结构或者跳转操作,但是由于在最开始就已经进行了初始化,因此在最后执行delete[]
操作是安全的。如果在分配了x1
并且在分配y1
之前,有其他操作直接跳转到了程序末尾,并且没有对y1
进行初始化,则会导致未定义行为。尽管代码可以在删除操作之前测试x1
和y1
是否为空,但实际上这样做是没有必要的。 - Jonathan Leffler删除空指针没有效果。虽然这不一定是良好的编码风格,因为它是不需要的,但也不算坏。
如果你正在寻找良好的编码实践,请考虑使用智能指针,这样你根本就不需要使用delete
。
只要您没有过载删除运算符,那么它就是安全的。但是如果您过载了删除运算符并且未处理null条件,则完全不安全。
关于这个问题,有一个常见问题解答可以回答。
C++语言保证如果p为空,则delete p不会执行任何操作。由于您可能会将测试反过来,并且由于大多数测试方法都要求您显式地测试每个分支点,因此您不应该放入冗余的if测试。
我有经验表明,在编程中删除[] NULL(即数组语法)是不安全的(VS2010)。我不确定这是否符合C++标准。
删除NULL(标量语法)是安全的。
delete[] NULL
。 - Konrad Rudolph
delete
命令。相反,应该使用RAII技术(资源获取即初始化)。例如,使用std::vector<T> v(100)
代替T* p = new T[100]
,使用智能指针如unique_ptr<T>
和shared_ptr<T>
等可以自动处理内存释放的指针,而不要使用原始指针等。 - fredoverflowmake_shared
和C++14中的make_unique
,您的程序应该不包含任何new
和delete
。 - sp2dannynew
或delete
。当标准组件无法完成任务时,设计用于管理资源的类可以做必要的操作,但重点是它们对所管理的内存执行丑陋的操作,而不是最终用户代码。因此,创建自己的库/辅助类来执行new
/delete
操作,并使用该类代替它们。 - underscore_d