safe_delete(p)的若干心得 #define safe_delete(p) do{ delete p; p=NULL; } while(false) 这种写法的意义不是显而易见的,而且还有另外一种版本的safe_delete(),在此就不写了,同样的令人费解——或者说让初学C++编程的人费解。 其实如此做的目的就是为了让程序更健壮。 一般的想法是do ... while()中的条件是false,那么这个do ... while()完全可以省略啊。OK,我们假设把这里的do ... while()省略,来看看在实际编程中会发生什么情况。 为了突出问题,我们只考虑这个语句块: if (NULL!=p) safe_delete(p) else ... 编译器把宏解开后(注意,我们现在考虑没有do ... while()的情况 ) if (NULL!=p) delete p; p=NULL; else ... 很明显,这个else失去配对的if。就算不存在else子句,问题依然存在,我们的本意是如果p!=NULL的话,才释放对象,并将p悬挂起来;但是这里却变成了,不论p是否为NULL,它都会被置NULL。程序在这句并不是按照你的预想执行的,也就有潜在的危险。 那我们把那两句话加上大括号行不行啊?我们还是尝试解开一下: if (NULL!=p) safe_delete(p) else ... 编译器把宏解开后(注意,我们现在考虑没有do ... while()的情况 ) if (NULL!=p) { delete p; p=NULL; } else ... 这样看来就没问题了。不过对于safe_delete()来说,它更像一个语句,所以可以想象某个程序员写完safe_delete()之后随手加了一个分号,就成了“safe_delete(p);”这样else又失去配对了。对于这个问题,可以考虑将safe_delete()全大写,以暗示程序员这个为宏定义,但是人嘛,总有马虎大意的时候,为了排除能想出来的一切可能性,我们就加上了do ... while()这个另人费解的循环。我们再看一下展开的结果: if (NULL!=p) do { delete p; p=NULL; } while(false) else ... 这样,对于之前提出的各种假设——else配对的问题;语句无条件被执行的问题;习惯性分号的问题,都可以杜绝。而且,对于这个do ... while()由于它是个假循环,不会影响效率(BCB6中会自动去掉这个循环)。它的意义完全在语意上。 以上这些假设,都是建立在safe_delete()写在库中,因为库的作者并不知道库的使用者会怎么用这个宏,他所能做的只是尽可能的减少这个宏出错的可能性,让使用者放心的使用。 |