new和delete的使用规范
2015-10-30 15:37
197 查看
C++的动态内存管理是通过new和delete两个操作来完成的,即用new来申请空间,用delete来释放空间。在使用new和delete时,注意以下原则。
(1)程序运行时,new操作和delete操作必须一一对应。
用new操作申请空间,如果申请成功,必须在以后的某个时刻用delete释放该空间,既不能忘记释放,也不能多次释放。前者会引起内存泄露,后者会引起运行时错误。如下面的程序。
以上程序对指针p所指向的空间进行两次释放,这种内存错误对C/C++的程序危害极大,也是很多人对C++语言忘而却步甚至的原因。多次释放同一块内存空见,并不一定立即引起程序运行错误,也不一定会导致程序运行的崩溃,这跟具体的编译器实现有关。但是,多次释放同一块内存空间绝对是一个编程错误,这个编程错误可能会在其后的某个时刻导致其他的逻辑错误的发生,从而给程序的调试和纠错带来困难。考察如下程序。
程序通过编译并运行结果:
003289A0
003289A0
003289A0
10
程序运行过程中会产生中断。从程序的输出可以看出,在将指针one所指向的空间释放后,为指针p申请的空间就是原来one所指向的空间。由于不小心在为p分配空间之后再次使用了delete one,导致q申请到的空间就是原来p所申请的空间,这样赋给*q的值就改写了原来p所指向的单元的值,导致最后输出结果为10。
由此可知,多次释放同一块内存空间,即使不导致程序运行中断,也会破坏环境,使指针与所对应的空间的隶属关系出现混乱,从而导致逻辑错误。在大型程序设计中,这种逻辑错误的查找会变得十分费时费力。
注意:当指针p的值为NULL时,多次使用delete p并不会带来麻烦,因为释放空指针的空间实际上不会导致任何操作。所以,将“不用”的指针设置为NULL是一个好的编程习惯。
(2)当类的成员中有指针变量时,在构造函数中用new申请空间并且在析构函数中用delete释放空间是一种“标准的”、安全的做法。
例如下面的程序。
程序运行输出:
In constructor,allocating space
name:张三
In destructor, free space
由于任何一个对象,其构造函数值调用一次,其析构函数也值调用一次,这样就嫩巩固保证运行时new和delete操作是一一对应的,也就是保证了内存管理的安全性。
在C++语言中,一个构造函数不能调用本类的另一个构造函数,其原因就是为了防止构造函数的相互调用打破了内存申请与释放之间的这种对应关系。
(1)程序运行时,new操作和delete操作必须一一对应。
用new操作申请空间,如果申请成功,必须在以后的某个时刻用delete释放该空间,既不能忘记释放,也不能多次释放。前者会引起内存泄露,后者会引起运行时错误。如下面的程序。
#include <iostream> using namespace std; int main(){ int *p; p=new int(3); if(p) delete p; delete p; return 0; }
以上程序对指针p所指向的空间进行两次释放,这种内存错误对C/C++的程序危害极大,也是很多人对C++语言忘而却步甚至的原因。多次释放同一块内存空见,并不一定立即引起程序运行错误,也不一定会导致程序运行的崩溃,这跟具体的编译器实现有关。但是,多次释放同一块内存空间绝对是一个编程错误,这个编程错误可能会在其后的某个时刻导致其他的逻辑错误的发生,从而给程序的调试和纠错带来困难。考察如下程序。
#include <iostream> using namespace std; int main(){ int *p,*q,*one; one=new int; if(one) cout<<one<<endl; delete one; p=new int(3); if(p) cout<<p<<endl; delete one;//假设这句语句是程序员不小心加上的 q=new int(5); if(q) cout<<q<<endl; cout<<(*p)+(*q)<<endl; delete p; delete q; }
程序通过编译并运行结果:
003289A0
003289A0
003289A0
10
程序运行过程中会产生中断。从程序的输出可以看出,在将指针one所指向的空间释放后,为指针p申请的空间就是原来one所指向的空间。由于不小心在为p分配空间之后再次使用了delete one,导致q申请到的空间就是原来p所申请的空间,这样赋给*q的值就改写了原来p所指向的单元的值,导致最后输出结果为10。
由此可知,多次释放同一块内存空间,即使不导致程序运行中断,也会破坏环境,使指针与所对应的空间的隶属关系出现混乱,从而导致逻辑错误。在大型程序设计中,这种逻辑错误的查找会变得十分费时费力。
注意:当指针p的值为NULL时,多次使用delete p并不会带来麻烦,因为释放空指针的空间实际上不会导致任何操作。所以,将“不用”的指针设置为NULL是一个好的编程习惯。
(2)当类的成员中有指针变量时,在构造函数中用new申请空间并且在析构函数中用delete释放空间是一种“标准的”、安全的做法。
例如下面的程序。
#include <iostream> using namespace std; class Student{ char* name; public: Student(){ cout<<"Default constructor"<<endl; } Student(char*); ~Student(); }; Student::Student(char*s){ //Student();//此句运行时报错,构造函数不能调用其他构造函数 cout<<"In constructor,allocating space"<<endl; name=new char[strlen(s)+1]; strcpy(name,s); cout<<"name:"<<name<<endl; } Student::~Student(){ cout<<"In destructor, free space"<<endl; delete name; } int main(){ Student s1("张三"); }
程序运行输出:
In constructor,allocating space
name:张三
In destructor, free space
由于任何一个对象,其构造函数值调用一次,其析构函数也值调用一次,这样就嫩巩固保证运行时new和delete操作是一一对应的,也就是保证了内存管理的安全性。
在C++语言中,一个构造函数不能调用本类的另一个构造函数,其原因就是为了防止构造函数的相互调用打破了内存申请与释放之间的这种对应关系。
相关文章推荐
- noip2013 计数问题 (模拟)
- 如何使用Python3读写INI配置文件
- 简单Dream-登录em报错密码已经过期--实测已解决
- 数据库表横表变纵表
- oracle bitmap join index
- new和delete的使用规范
- UIApplicationLaunchOptionsRemoteNotificationKey
- 2014中国大数据技术大会33位核心专家演讲PDF下载
- Android中十六进制颜色的基本使用
- [Python]python环境配置
- 51.VC(Custom)-__super简介
- Jmeter中Websocket协议支持包的使用
- 如何解决jquery ui拖拽时拖到容器外会被覆盖问题
- Mockito java学习
- Android编程判断SD卡是否存在及使用容量查询实现方法
- BZOJ 4318 OSU! 期望DP
- 第一行代码Andorid——登录记住密码
- 关于解决移动页面固定宽度 缩放显示
- Android获取公历年/月/日/星期 + 农历月/日
- [转]PHP 应用性能分析 - Davey Shafik(全)