// 某个单例CxxxDemo* CxxxDemo::getInstance(){if (s_pInstance == nullptr){s_pInstance = new CxxxDemo();}return s_pInstance;}void CxxxDemo::destoryInstance(){delete s_pInstance;}// 使用demo = CxxxDemo::getInstance();// 省略中间代码.........CxxxDemo::destoryInstance();
大部分同学应该都发现了,单例的destoryInstance
函数没有在delete
之后将s_pInstance
置空。本次使用没问题,但下次getInstance
就会返回一个野指针。
分析这个问题,实际上就是在delete之后没有置空,那么问题来了:
我们在做Code Review时是否要将delete后必须置空作为一条规则呢?
首先我们来看看如果delete后都统一置空,会怎样呢?
分以下两种情况:
看起来在delete后置空是有百利而无一害的,那么问题又来了:
C++为什么不在delete后直接强行置空呢?
在C++ Standard的FAQ里我们找到这么一段回答:
Since deleting a null pointer is harmless by definition, a simple solution would be for delete p; to do a p=nullptr; after it has done whatever else is required. However, C++ doesn’t guarantee that. One reason is that the operand of delete need not be an lvalue.
理由很简单,delete后面跟随的不一定是左值。
所以我们在delete之后一定要手动置空吗?
在我们这份代码里,逻辑使然是必须的。但如果是一个常规的指针,我们的预期往往是delete之后就不会再被使用了,如果程序因为逻辑异常再次使用了该指针,你在delete之后置空虽然可以避免野指针相关的程序崩溃,但也会导致这个逻辑异常不易被暴露出来。
综上所述,关于指针的delete问题我们有以下三点建议:
后续我们会在每周二分享一些Code Review中遇到的问题,以及常用的方法和工具。大家对于Code Review有什么见解也欢迎一起交流讨论。