当前位置: 首页 > news >正文

C++ new和delete动态分配和释放内存

关于C++的关键字兼运算符: new 和 delete

new

new关键字其实就是告诉计算机开辟一段新的空间,但是和一般的声明不同的是,new关键字开辟的空间在堆内存上,而一般声明的变量存放在栈内存上.通常来说,当在局部函数中new出一段新的空间,该段空间在局部函数调用结束后仍然能够使用,可以用来向主函数传递参数,另外需要注意的是,new的使用格式,new出来的是一段空间的首地址.所以一般需要用指针来存放这段地址


为什么需要new来开辟内存空间:

比如说数组的长度是预先定义好的,在整个程序中固定不变,但C++ 不允许定义元素个数不确定的数组,例如:

int n;//未进行定义的变量n
int a[n];  //这种定义是不允许的

但是在实际的编程中,往往会出现所需的内存空间大小取决于实际要处理的数据多少,而实际要处理的数据数量在编程时无法确定的情况。如果总是定义一个尽可能大的数组,又会造成空间浪费.何况,这个“尽可能大”到底应该多大才够呢

为了解决上述问题,C++提供了一种动态内存分配机制 ,使得程序可以在运行期间,根据实际需要,要求操作系统临时分配一片内存空间用于存放数据.此种内存分配是在程序运行中进行的,而不是在编译时就确定的,因此称为“动态内存分配”

总结:动态内存分配是一种,内存分配是在程序运行中进行的,而不是在编译时就确定的内存分配方式


C++ 中,通过new运算符来实现动态内存分配,new运算符的第一种用法如下:

T *p = new M;

其中M任意类型名,p类型为T*的指针

这个语句会动态分配出一片大小为sizeof(M)字节大小的内存空间,且将这段内存空间的起始地址(首地址)赋值给int类型的指针p,例如:


典型的new使用方式

int *p;
p=new int;
*p=5;

第一行 :建立类型为int的指针p
第二行p=new int此行动态分配了一片4个字节大小(int)的内存空间,而指针p指向指向这片空间
第三行:通过p读写这片空间


在使用new动态分配内存空间的同时对指针值进行定义

int* p = new int(123);//可以之间在new对象中进行初始化
cout<< *p << endl;//输出结果为 “123”

使用new动态分配内存一个任意大小的数组

例如:

T *p =new M[N];

在以上代码中
M任意类型名
p是类型为T*的指针
N代表示元素个数
[]内的值可以为任何值为正整数的表达式(表达式内可包含你变量和函数调用等值),以上语句动态分配出N x sizeof(M)个字节的内存空间这片空间的起始地址被赋值给p,例如:

//todo使用new申请多个对象,例如申请1024个int对象如下:
	int* p2 = new int[10];//用[]指定对象的个数
	cout << "使用new申请多个对象的结果为:\n\n";
	for (int i = 0; i < 10; i++)
	{
		p2[i] = i + 1;
		cout << p2[i]<< endl;//打印指针数组时直接输入数组名即可 因为数组名就是数组指针的首地址
	}

	delete[] p2;//如果new的时候用了[],则释放的时候使用delete[]操作符

结果:
在这里插入图片描述

注意: 如果new的时候用了[],则释放的时候使用delete操作符后面也要跟上一个[]符号,表示释放数组中的所有元素


delete

程序从操作系统动态分配所得的内存空间在使用完后应该释放,交还操作系统,以便操作系统将这片内存空间分配给其他程序使用.C++ 中提供了delete 运算符,用以释放动态分配的内存空间.delete运算符的基本用法如下:

在动态分配一般变量的内存时:

int p=new int;
delete p;

在动态分配数组变量的内存时:

int p=new int[10];
delete []p;

其中,p是指向动态分配内存的指针,且p必须指向动态分配(new)的内存空间,否则运行时将报错,例如:

int* p = new int;
*p = 5;
delete p;
delete p;  //本句会导致程序出错

int* p = NULL;//将p这个指针变量设置为NULL,防止野指针的出现和内存泄漏

上面的第一条delete语句正确地释放了动态分配的4个字节内存空间,第二条delete语句会导致程序出错,因为p所指向的空间已经释放,此时指针变量p虽然不再是指向动态分配的内存空间的指针了,但此时p这个指针还存在,但此指针已不指向任何一段内存,为了 防止内存的泄漏和野指针的出现,我们还需将p这个指针变量设置为NULL


注意:🎯

1如果动态分配了一个数组,但是却用delete p的方式释放,没有用[],则编译时没有问题,运行时也一般不会发生错误,但实际上会导致动态分配的数组没有被完全释放

2.牢记,用 new 运算符动态分配的内存空间,一定要用 delete 运算符释放.否则,即便程序运行结束,这部分内存空间仍然不会被操作系统收回,从而成为被白白浪费掉的内存垃圾.这种现象也称为内存泄露

3.如果一个程序不停地进行动态内存分配而总是没有释放,那么可用内存就会被该程序大量消耗,即便该程序结束也不能恢复.这就会导致操作系统运行速度变慢,甚至无法再启动新的程序.但是,只要重新启动计算机,这种情况就会消失

4.编程时如果进行了动态内存分配,那么一定要确保其后的每一条执行路径都能释放它,另外还要注意,释放一个指针,并不会使该指针的值变为 NULL(也就是说释放后指针的指向的变量的值不变)

来自
C++ new和delete(C++动态分配和释放内存)🔍
源自C++ 虚方法项目

相关文章:

  • C++ 类对象与类指针(静态和动态多态)
  • 第六天 if if…else 三木运算符
  • C++ 虚函数与多态性
  • pb11.2build8949 数据窗口dw limit有关问题
  • VS 监视功能
  • C++ 抽象类
  • C++ 运算符重载
  • 购买Microsoft Technet订阅,免费获得微软几乎所有的产品序列号“用于评估”,...
  • C++ 操作符重载
  • 客户端调用webservice的两种方式
  • C++ 多继承
  • redmine 主题thems-默认主题
  • C++ 虚继承
  • C++ 错误处理和调试(编写代码前的准备工作)
  • 将整型数字转换为大写汉字的自定义函数,如转换为'壹贰
  • 10个最佳ES6特性 ES7与ES8的特性
  • 2018一半小结一波
  • CSS相对定位
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • java8 Stream Pipelines 浅析
  • JAVA之继承和多态
  • miaov-React 最佳入门
  • mockjs让前端开发独立于后端
  • MySQL-事务管理(基础)
  • Quartz初级教程
  • Vue组件定义
  • Webpack入门之遇到的那些坑,系列示例Demo
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 搭建gitbook 和 访问权限认证
  • 给自己的博客网站加上酷炫的初音未来音乐游戏?
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 详解NodeJs流之一
  • 新版博客前端前瞻
  • 一个JAVA程序员成长之路分享
  • 鱼骨图 - 如何绘制?
  • UI设计初学者应该如何入门?
  • 阿里云ACE认证之理解CDN技术
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • #NOIP 2014#Day.2 T3 解方程
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • ${ }的特别功能
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .net 7 上传文件踩坑
  • .NET Core WebAPI中封装Swagger配置
  • .net core使用RPC方式进行高效的HTTP服务访问
  • .NET 表达式计算:Expression Evaluator
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)...
  • @Query中countQuery的介绍
  • [2019.3.20]BZOJ4573 [Zjoi2016]大森林