#define SAFE_DELETE(a) if( (a) != NULL ) delete (a); (a) = NULL;
或者
template<typename T> void safe_delete(T*& a) {
delete a;
a = NULL;
}
或任何其他更好的方式
#define SAFE_DELETE(a) if( (a) != NULL ) delete (a); (a) = NULL;
或者
template<typename T> void safe_delete(T*& a) {
delete a;
a = NULL;
}
或任何其他更好的方式
我不会说,因为两者都会给你一种虚假的安全感。例如,假设您有一个函数:
void Func( SomePtr * p ) {
// stuff
SafeDelete( p );
}
您将 p 设置为 NULL,但函数外部的 p 副本不受影响。
但是,如果您必须这样做,请使用模板 - 宏总是有可能超越其他名称。
删除一个;
ISO C++ 规定,对 NULL 指针的删除不做任何事情。
引自 ISO 14882:
5.3.5 删除[expr.delete] 2 [...] 在任一备选方案中,如果 delete 的操作数的值是 空指针操作无效。[...]
问候, 博多
/edit:我没有注意到 a=NULL; 在原来的帖子中,所以新版本:删除一个;一个=空;但是,已经指出了设置 a=NULL 的问题(错误的安全感)。
很明显的功能,原因很简单。宏多次评估其参数。这可能会产生不良的副作用。该功能也可以限定范围。没有比这更好的了:)
一般来说,比起宏,更喜欢内联函数,因为宏不考虑作用域,并且在预处理过程中可能会与某些符号冲突,从而导致非常奇怪的编译错误。
当然,有时模板和函数是不行的,但这里不是这样。
此外,不需要更好的安全删除,因为您可以使用智能指针,因此不需要记住在客户端代码中使用此方法,而是将其封装。
(编辑)正如其他人指出的那样,安全删除并不安全,即使有人没有忘记使用它,它仍然可能达不到预期的效果。所以它实际上完全没有价值,因为正确使用 safe_delete 需要更多的思考,而不仅仅是自己设置为 0。
您不需要使用 来测试无效性delete
,它相当于无操作。(a) = NULL
让我挑眉。第二种选择更好。
但是,如果您有选择,您应该使用智能指针,例如std::auto_ptr
or tr1::shared_ptr
,它已经为您执行此操作。
我认为
#define SAFE_DELETE(pPtr) { delete pPtr; pPtr = NULL }
更好
SAFE_DELETE 的使用似乎是 C 程序员在 C++ 中控制内置内存管理的一种方法。我的问题是:C++ 是否允许在已正确封装为 Private 的指针上使用 SAFE_DELETE 的这种方法?此宏是否仅适用于声明为 Public 的指针?糟糕!
如上所述,第二个更好,不是具有潜在意外副作用的宏,没有对 NULL 的不必要检查(尽管我怀疑您是在进行类型检查)等等。但是两者都没有承诺任何安全性。如果您确实使用了 tr1::smart_ptr 之类的东西,请确保您阅读了它们的文档并确保它具有适合您任务的语义。由于同事将 smart_ptrs 放入具有循环链接的数据结构中,我最近不得不寻找并清理巨大的内存泄漏:)(他应该使用weak_ptrs 进行反向引用)
我更喜欢这个版本:
~scoped_ptr() {
delete this->ptr_; //this-> for emphasis, ptr_ is owned by this
}
在删除指针后将指针设置为 null 毫无意义,因为您使用指针的唯一原因是允许一次在多个位置引用一个对象。即使程序某一部分的指针为 0,也可能有其他部分未设置为 0。
此外,safe_delete 宏/函数模板很难正确使用,因为如果在给定指针的 new 和 delete 之间存在可能抛出的代码,则只有两个地方可以使用它。
1) 在重新抛出异常的 catch (...) 块内,并在不抛出的路径的 catch (...) 块旁边复制。(在每个可能允许指针超出范围的中断、返回、继续等旁边也重复)
2) 在拥有指针的对象的析构函数中(除非在 new 和 delete 之间没有可以抛出的代码)。
即使在您编写代码时没有可能抛出的代码,这也可能在未来发生变化(只需有人出现并在第一个代码之后添加另一个新代码)。最好以即使面对异常也保持正确的方式编写代码。
选项 1 产生了如此多的代码重复并且很容易出错,以至于我什至怀疑将其称为选项。
选项 2 使 safe_delete 变得多余,因为您设置为 0 的 ptr_ 将超出下一行的范围。
总之——不要使用 safe_delete,因为它根本不安全(正确使用非常困难,即使使用正确也会导致冗余代码)。使用 SBRM 和智能指针。