A: 嗯,问得挺有道理的。我们来看:
delete p;
// ...
delete p;
如果代码中的//...部分没有再次给p分配内存,那么这段代码就对同一片内存释放了两次。这是个严重的错误,可惜C++无法有效地阻止你写这种代码。不过,我们都知道,释放空指针是无危害的,所以如果在每一个delete
p;后面都紧接一个p =
0;,那么两次释放同一片内存的错误就不会发生了。尽管如此,在C++中没有任何语法可以强制程序员在释放指针后立刻将该指针归零。所以,看来避免犯这样的错误的重任只能全落在程序员肩上了。或许,delete自动把指针归零真是个好主意?
哦,不不,这个主意不够“好”。一个理由是,被delete的指针未必是左值。我们来看:
delete p+1;
delete f(x);
你让delete把什么自动置零?也许这样的例子不常见,但足可证明“delete自动把指针归零”并不保险。[译注:事实上,我们真正想要的是:“任何指向被释放的内存区域的指针都被自动归零”——但可惜除了Garbage
Collector外没什么东东可以做到这点。] 再来看个简单例子:
T* p = new T;
T* q = p;
delete p;
delete q; // ouch!
C++标准其实允许编译器实作为“自动把传给delete的左值置零”,我也希望编译器厂商这样做,但看来厂商们并不喜欢这样。一个理由就是上述例子——第3行语句如果delete把p自动置零了又如何呢?q又没有被自动置零,第4行照样出错。
如果你觉得释放内存时把指针置零很重要,那么不妨写这样一个destroy函数:
template<class T> inline void destroy(T*& p) { delete p; p = 0; }
不妨把delete带来的麻烦看作“尽量少用new/delete,多用标准库中的容器”之另一条理由吧
:O)
请注意,把指针作为引用传递(以便delete可以把指针置零)会带来额外的效益——防止右值被传递给destroy() :
int* f();
int* p;
// ...
destroy(f()); // error: trying to pass an rvalue by non-const reference
destroy(p+1); // error: trying to pass an rvalue by non-const reference
原文地址:http://www.research.att.com/~bs/bs_faq2.html#delete-zero
本文乃网上搜集得来,其版权归原作者和原出处所有。如有侵犯版权之处请与我联系,我将马上进行处理。