哪个版本的 safe_delete 更好?
#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;
OR
template<typename T> void safe_delete(T*& a) {
delete a;
a = NULL;
}
or any other better way
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
我不会说,因为两者都会给你一种错误的安全感。 例如,假设您有一个函数:
您将 p 设置为 NULL,但函数外部的 p 副本不受影响。
但是,如果您必须这样做,请使用模板 - 宏总是有可能取代其他名称。
I would say neither, as both will give you a false sense of security. For example, suppose you have a function:
You set p to NULL, but the copies of p outside the function are unaffected.
However, if you must do this, go with the template - macros will always have the potential for tromping on other names.
功能很明显,原因很简单。 该宏多次评估其参数。 这可能会产生邪恶的副作用。 该函数也可以限定作用域。 没有比这更好的了:)
Clearly the function, for a simple reason. The macro evaluates its argument multiple times. This can have evil side effects. Also the function can be scoped. Nothing better than that :)
删除一个;
ISO C++ 规定,对 NULL 指针进行删除不会执行任何操作。
引用 iso 14882:
问候,Bodo
/编辑:我没有注意到 a=NULL; 在原来的帖子中,所以新版本:删除一个; a=空; 然而,设置 a=NULL 的问题已经被指出(错误的安全感)。
delete a;
ISO C++ specifies, that delete on a NULL pointer just doesn't do anything.
Quote from iso 14882:
Regards, Bodo
/edit: I didn't notice the a=NULL; in the original post, so new version: delete a; a=NULL; however, the problem with setting a=NULL has already been pointed out (false feeling of security).
通常,与宏相比,更喜欢内联函数,因为宏不考虑范围,并且可能在预处理期间与某些符号发生冲突,从而导致非常奇怪的编译错误。
当然,有时模板和函数不起作用,但这里不是这种情况。
此外,更好的安全删除不是必需的,因为您可以使用智能指针,因此不需要记住在客户端代码中使用此方法,而是封装它。
(编辑)正如其他人所指出的,安全删除并不安全,因为即使有人没有忘记使用它,它仍然可能达不到预期的效果。 所以它实际上是完全没有价值的,因为正确使用 safe_delete 需要更多的思考而不仅仅是自己设置为 0。
Generally, prefer inline functions over macros, as macros don't respect scope, and may conflict with some symbols during preprocessing, leading to very strange compile errors.
Of course, sometimes templates and functions won't do, but here this is not the case.
Additionally, the better safe-delete is not necessary, as you could use smart-pointers, therefore not requiring to remember using this method in the client-code, but encapsulating it.
(edit) As others have pointed out, safe-delete is not safe, as even if somebody does not forget to use it, it still may not have the desired effect. So it is actually completely worthless, because using safe_delete correctly needs more thought than just setting to 0 by oneself.
您不需要使用
delete
测试无效性,它相当于无操作。(a) = NULL
让我扬起了眉毛。 第二种选择更好。但是,如果您有选择,您应该使用智能指针,例如
std::auto_ptr
或tr1::shared_ptr
,它们已经为您完成了此操作。You don't need to test for nullity with
delete
, it is equivalent to a no-op.(a) = NULL
makes me lift an eyebrow. The second option is better.However, if you have a choice, you should use smart pointers, such as
std::auto_ptr
ortr1::shared_ptr
, which already do this for you.我认为
#define SAFE_DELETE(pPtr) {删除pPtr; pPtr = NULL } 更好的是,
I think
#define SAFE_DELETE(pPtr) { delete pPtr; pPtr = NULL }
is betterSAFE_DELETE 的使用实际上似乎是 C 程序员控制 C++ 中内置内存管理的一种方法。 我的问题是:C++ 是否允许在已正确封装为 Private 的指针上使用 SAFE_DELETE 的这种方法? 该宏仅适用于声明为 Public 的指针吗? 糟糕!
Usage of SAFE_DELETE really appears to be a C programmers approach to commandeering the built in memory management in C++. My question is: Will C++ allow this method of using a SAFE_DELETE on pointers that have been properly encapsulated as Private? Would this macro ONLY work on pointer that are declared Public? OOP BAD!!
正如上面提到的,第二个是更好的一个,不是一个具有潜在意外副作用的宏,没有对 NULL 进行不必要的检查(尽管我怀疑您正在这样做作为类型检查),等等。但是两者都没有承诺任何安全。 如果您确实使用了 tr1::smart_ptr 之类的东西,请确保您阅读了它们的文档,并确保它具有适合您的任务的语义。 我最近不得不寻找并清理一个巨大的内存泄漏,因为一位同事将 smart_ptrs 放入带有循环链接的数据结构中:)(他应该使用weak_ptrs作为反向引用)
As mentioned quite a bit above, the second one is the better one, not a macro with potential unintended side effects, doesn't have the unneeded check against NULL (although I suspect you are doing that as a type check), etc. But neither are promising any safety. If you do use something like tr1::smart_ptr, please make sure you read the docs on them and are sure that it has the right semantics for your task. I just recently had to hunt down and clean up a huge memory leak due to a co-worker putting smart_ptrs into a data structure with circular links :) (he should have used weak_ptrs for back references)
我更喜欢这个版本:
删除指针后将其设置为 null 是毫无意义的,因为使用指针的唯一原因是允许一次在多个位置引用一个对象。 即使程序中某一部分的指针为 0,也可能有其他部分没有设置为 0。
此外,safe_delete 宏/函数模板很难正确使用,因为只有两个地方可以使用它:对于给定的指针,有一些代码可能会在 new 和 delete 之间抛出。
1) 在重新抛出异常的 catch (...) 块内,并且在不抛出异常的路径的 catch (...) 块旁边复制。 (也在每个可能允许指针超出范围的中断、返回、继续等旁边重复)
2)在拥有指针的对象的析构函数内(除非 new 和 delete 之间没有可以抛出的代码) 。
即使在编写代码时没有可能抛出的代码,这种情况将来也可能会发生变化(所需要的只是有人出现并在第一个代码之后添加另一个新代码)。 最好以即使面对异常也能保持正确的方式编写代码。
选项 1 创建了如此多的代码重复,并且很容易出错,以至于我什至怀疑是否可以将其称为选项。
选项 2 使 safe_delete 变得多余,因为设置为 0 的 ptr_ 将超出下一行的范围。
总之——不要使用 safe_delete,因为它根本不安全(正确使用它非常困难,即使使用正确也会导致冗余代码)。 使用 SBRM 和智能指针。
I prefer this version:
Setting the pointer to null after deleting it is quite pointless, as the only reason that you would use pointers is to allow an object to be referenced in multiple places at once. Even if the pointer in one part of the program is 0 there may well be others that are not set to 0.
Furthermore the safe_delete macro / function template is very difficult to use right, because there are only two places that it can be used if there is code that may throw between the new and delete for the given pointer.
1) Inside either a catch (...) block that rethrows the exception and also duplicated next to the catch (...) block for the path that doesn't throw. (Also duplicated next to every break, return, continue etc that may allow the pointer to fall out of scope)
2) Inside a destructor for an object that owns the pointer (unless there is no code between the new and delete that can throw).
Even if there is no code that could throw when you write the code, this could change in the future (all it takes is for someone to came along and add another new after the first one). It is better write code in a way that stays correct even in the face of exceptions.
Option 1 creates so much code duplication and is so easy to get wrong that I am doubtful to even call it an option.
Option 2 makes safe_delete redundant, as the ptr_ that you are setting to 0 will go out of scope on the next line.
In summary -- don't use safe_delete as it is not safe at all (it is very difficult to use correctly, and leads to redundant code even when its use is correct). Use SBRM and smart pointers.