在c++中,经常会使用new和delete来动态申请和释放内存。
特别的,delete指针之后,一定要给指针赋值为空,不然会引起程序崩溃。
T* p = new T();
delete p;
// ...
p->func(); // crash
if (p) {
p->func(); // crash too
}
以上代码,因为指向的内存已经被释放,导致后面的调用失效,这种情况导致程序崩溃的原因会非常难找,而且出错的位置很难定位,开发时往往还容易遇到很多这种情况。
那么delete到底做了什么动作呢?
delete指针只是释放了那个指针原本所指的内存而已,并没有删除该指针。如上代码所示,被delete后的指针p的值(地址值)并非就是nullptr值,而是随机值。因此,指针被delete后,如果不置为空,那么指针p就成了野指针,就会在内存里乱指一通。但若在那个函数里delete了p后,又没再给p赋值(地址值),再次调用p就危险了,因为这时p在内存里乱指,有可能指到一些重要地址,随时可能系统崩溃。
那么置空指针到底是解决了什么问题?
在指针变量申明或者delete指针后,如果没有确切的地址可以赋值,一般会给指针置空。
一方面,在大多数操作系统上,程序不允许访问地址为0的内存,因为该内存是操作系统保留的,因此内存地址0有特别重要的意义,表明该指针不指向一个可以访问的内存地址。
另一方面,nullptr最大的优势在于值是明确的,也就是说分辨一个指针是不是nullptr,比分辨一个指针是不是野指针要容易得多。那delete后置空指针的最大价值就在于明确资源当前状态。你想判断一个资源是否有效时,你当然没法直接跑去看这个资源在不在,而是得询问资源的持有者是否仍然持有这个资源。如果所有被delete的指针都被置为nullptr,之后再去访问这个指针的时候,我们可以通过其与nullptr的比较轻松判断出资源是否已经被delete。
判断一个指针是否为空指针,可以用if语句,比如:
if(ptr) /* 如果 ptr 非空,则完成 */
if(!ptr) /* 如果 ptr 为空,则完成 */
常见问题:
常见问题1:能delete一个空指针吗?
可以,因为实际上delete 本身会自动检查对象是否为空 .如果为空 , 就不做操作
常见问题2:对一个非空指针delete后,若没有赋nullptr,若再次delete可行吗?
如下:
int *p = new int(3);
delete p;
delete p;
不行。不能删除两次,第一次delete p之后,p的地址并不是空,同一块内存释放两次会导致崩溃。
但是,如果代码改为以下:
1 int *p = new int(3);
2 delete p;
3 p = nullptr;
4 delete p;
则是可行的,因为delete一个空指针是合法的。 所以为了防止多次delete指针导致程序崩溃,需要养成良好习惯进行置空。
参考: https://www.cnblogs.com/hazir/p/new_and_delete.html