delete指针以后应赋值为NULL
delete p后,只是释放了指针中存放的地址中的内存空间。但是指针变量p仍然存在(即指针p本身所占有的内存),且p中存放的地址还是原来的地址。
例如:
对一个非空指针delete后,若没有将p赋为NULL,若再次delete的话,会出现问题。
如下代码:
#include <iostream>
int main()
{
int* p = new int();
delete p;
delete p;
return ;
}
在ubuntu14.04中使用g++进行编译无问题,但运行时报错如下:

意思就是对同一指针变量进行了两次释放内存的操作,这是不合法的。
因为第一次释放后,指针p指向的那块区域已经变为不可访问区域了,再执行一次delete p,试图对一块不可访问的区域进行释放,这是不合法的。
将其改为:
#include <iostream>
int main()
{
int* p = new int();
delete p;
p = NULL;
delete p;
return ;
}
则编译和运行都没有问题,因为C++保证delete值为NULL的指针是安全的。
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
具体的说明如下:
还是先看代码:
/*
*Compile Environment:linux ubuntu14.04.5 g++
*Author: mengjia
*Date:20180520
**/
#include <iostream>
using namespace std;
int main()
{
int *p = new int;
*p = ;
cout << "将3赋给p的地址后,指针p读取的值:" << *p << endl;
cout << "删除空间前,指针p中存放的地址:" << p <<endl;
delete p;
cout<<"删除空间后,指针p存放的地址:"<< p <<endl; //在vs2017中,p中存放的地址会改变,但在g++中不会,应该是vs2017中对其进行优化了,让p指向了一个不可访问的地址,避免delete之后又误操作了p
cout << "删除空间后,指针p读取的值:" << *p << endl; //在vs2017中,对×p的访问直接会报错(引发了异常: 读取访问权限冲突),但在g++中,可
以正常往下执行。
long *p1 = new long;
*p1 = ;
cout << "创建新空间后,指针p中存放的地址:" << p << endl;
cout << "指向新空间的指针p1存放的地址:" << p1 << endl;
*p = ;
cout << "将23赋给p的地址后,指针p读取的值:" << *p << endl;
cout << "将23赋给p的地址后,指针p1读取的值:" << *p1 << endl;
delete p1;
// system("pause");
return ;
}
输出结果为:

从第13和第15行中可以看到,delete指针p前后,p中存放中地址并未改变。这就说明一个非常重要的结论:
delete一个指针后,编译器只是释放了指针中存放的地址中的内存空间,但p中存放的地址还是原来的地址。
在程序的第18行,创建了一个long型的指针p1,在20和21行的输出中发现,指针p保存的地址居然和指针p1保存的地址一毛一样。说明指针p和指针p1都指向内存的同一个地方。出现这种状态是因为编译器默认将释放掉的内存空间回收然后分配给新开辟的空间。所以行,当开辟一个可以保存long型变量的空间并且由p1来指向它时,分配的空间为p指向的内存空间。
如此,将导致两个指针同时指向同一内存空间。这在C++中是非常忌讳的。
如上,在程序中定义了*p1 = 100;而后再操作p,使*p = 23;而后读取p1指向的内存中的值,变为了23。这就会使得已经delete的指针,若操作不当,会影响到程序的其它指针。这种情况就是由于野指针p造成的。
要避免这种情况的发生,解决办法就是:
在删除一个指针之后,一定要将该指针设置成空指针,即在delete p之后,要加上: p = NULL
补充说明:
请注意程序中第15行和16行的注释,这段程序在vs2017上是编译不通过的。原因就如注释所言,vs2017对其进行了优化,delete之后,让p的指向改变了,改变为指向一个不可访问的地址,使得之后如果有任何*p相关的操作,都会直接报错。其目的,我觉得就是保证在源头断绝,不让出现野指针的情况。
但这种依赖于编译器的优化,对我们理解C++并没有好处。
delete指针以后应赋值为NULL的更多相关文章
- delete指针以后应赋值为NULL——QT deletelater指针以后也同样要马上赋值为NULL
delete p后,只是释放了指针指向的内存空间.p并不会自动被置为NULL,而且指针还在,同时还指向了之前的地址 delete NULL编译器不会报错(因为delete空指针是合法的) 例: 对一个 ...
- C++在delete指针后要赋值为NULL
C++标准规定:delete空指针是合法的,没有副作用. 所以我们在Delete指针后赋值为NULL或0是个好习惯.对一个非空指针delete后,若没有赋NULL,若再次delete的话 有可能出现问 ...
- [转载]delete指针之后应该赋值NULL
首先,C++标准规定:delete空指针是合法的,没有副作用.但是,delete p后,只是释放了指针指向的内存空间.p并不会自动被置为NULL,而且指针还在,同时还指向了之前的地址. 问题来了,对一 ...
- 指针delete之后赋值为null
1.现象 经常看到有些代码在delete之后赋值为null 2.原因 C++标准规定:delete空指针是合法的,没有副作用. 所以我们在Delete指针后赋值为NULL或0是个好习惯.对一个非空指针 ...
- C语言_指针变量的赋值与运算,很详细
指针变量的赋值 指针变量同普通变量一样,使用之前不仅要定义说明, 而且必须赋予具体的值.未经赋值的指针变量不能使用, 否则将造成系统混乱,甚至死机.指针变量的赋值只能赋予地址, 决不能赋予任何其它数据 ...
- C++ 指针悬挂和赋值操作符的重载,拷贝构造函数实现
指针悬挂: 问题:使用new申请的内存内存空间无法访问,也无法释放. 原因:直接对指向new申请的存储空间的指针变量进行赋值修改 后果:失去了原来的地址,原来的空间无法访问也无法释放,造成内存泄漏 还 ...
- 【Java讨论】引用类型赋值为null对加速垃圾回收的作用(转载)
:有一些人认为等于null可以帮助垃圾回收机制早点发现并标识对象是垃圾.其他人则认为这没有任何帮助.是否赋值为null的问题首先在方法的内部被人提起.现在,为了更好的阐述提出的问题,我们来撰写一个Wi ...
- delete 指针
#include<iostream>using namespace std;class human{public: human(){cout<<"构造";} ...
- [No000017C]改善C#程序的建议5:引用类型赋值为null与加速垃圾回收
在标准的Dispose模式中(见前一篇博客“C#中标准Dispose模式的实现”),提到了需要及时释放资源,却并没有进一步细说让引用等于null是否有必要. 有一些人认为等于null可以帮助垃圾回收机 ...
随机推荐
- python 面向对象(五)约束 异常处理 MD5 日志处理
###############################总结###################### 1.异常处理 raise:抛出异常 try: 可能出现错误代码 execpt 异常类 a ...
- Nlog日志组件简介
NLog简介 NLog是一个简单灵活的.NET日志记录类库,NLog的API非常类似于log4net,配置方式非常简单.支持多种形式输出日志:文本文件.系统日志.数据库.控制台.邮箱等 1.NLog简 ...
- WebStorm记录(1)
开始写前端,使用WebStorm,记录下使用过程 参考 WebStorm 初步使用 & HTML5 学习报告 webstorm怎么运行调试html WebStorm 快速开发教程 --CSS篇 ...
- PHP7 网络编程(六)Socket和IO多路复用【待】
https://blog.csdn.net/zhang197093/article/details/77366407
- Linux系统中用户组、文件权限浅解
用户组 在linux中的每个用户必须属于一个组,不能独立于组外.在Linux中每个文件有所有者.所在组.其它组的概念. [所有者] 一般为文件的创建者,谁创建了该文件,就天然的成为该文件的所有者,用& ...
- 转换流InputStreamReader & OutputStreamWriter
转换流InputStreamReader & OutputStreamWriter 比如当使用FileReader读取文件时,可以读取IDE默认的UTF-8编码的文件,但是当有一个文件是GBK ...
- Python实现工厂模式
from abc import ABCMeta, abstractmethod from enum import Enum class Person(metaclass=ABCMeta): @abst ...
- [转载]SpringMVC解决跨域问题
本文转载自 https://www.cnblogs.com/morethink/p/6525216.html SpringMVC解决跨域问题, 感谢作者! 有个朋友在写扇贝插件的时候遇到了跨域问题. ...
- 几本不错的数据仓库和Hadoop书籍
<<Pentaho Kettle解决方案:使用PDI构建开源ETL解决方案>>, Matt Casters等著,初建军翻译<<Hadoop应用架构>> ...
- matplotlib-区域填充
import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl import datetime #解决能显示中文 ...