C++内存管理初探

C/C++中程序中内存区域简单划分及介绍

空间划分
内核空间:存放内核代码和数据的空间,提供给内核使用

栈(堆栈):存储非静态局部变量/实例化后的形参/返回值等等数据的空间,栈向下增长(即从高地址处向低地址处生长)。

内存映射段:用于高效映射I/O映射,装载共享动态库的空间。用户可使用系统接口创建共享内存,做进程间通信

:在程序运行时用于动态分配的空间,堆向上增长,程序员申请,必须由程序员释放。

数据段:存储全局数据与静态(static)数据,程序结束时由系统释放

代码段:可执行的代码/只读常量

这篇文章主要集中于C++内存管理,如果有铁汁儿想先回忆一下C语言动态内存管理,移步此处动态内存管理

C++内存管理方式

在C++中,我们仍然可以使用C语言的库函数malloc/calloc/realloc实现内存分配。
在这里插入图片描述
但C++有更好的方法——new运算符,再次强调!运算符new!!!

我们先来试试叭!

使用new分配内存

在运行阶段为一个int值分配未命名的空间,使用指针去访问这个值。

int* pt = new int;

new int告诉程序,需要适合存储一个int数据的空间。new根据类型确定需要多少字节的内存,找到后返回该空间的地址。

为一个数据对象(内置/自定义)获得并制定分配内存的格式如下:

typeName* pointer_name = new typeName;

上面这个仅是申请一个typeName型数据空间的通用格式

那么申请了,释放怎么办?往下看

使用delete释放内存

我们使用完new得到的内存后,当然要释放了!因为new申请的空间仍然在堆上,所以我们还是要自己手动释放,此时应用到delete,将空间归还给系统。这与mallocfree并无二致,自己申请,自己释放。

使用delete释放空间,要给delete后加上被申请空间的指针,就像free释放malloc申请的空间一样,需要指针的传入。如下:

typeName* pointer_name = new typeName;
{//业务处理完成}
delete pointer_name;//delete释放空间

[Note]:
1.只能用delete释放new申请的空间!这两个是cp,不能拆开,同理,malloc与free也是cp,它们不能混搭使用。

2.不要尝试用delete释放已经释放了的空间! C++标准指出,这么做的结果是不确定的。但对nullptr来讲是安全的,也就是说,除nullptr外,其它指针不能被释放两次及以上

使用new申请动态数组

通用格式如下:

typeName* pointer_name = new typeName[number];

这条语句在程序运行时会申请一个可以存放numbertypeName类型数据的空间,并将该空间的地址赋给pointer_name,之后我们就能使用申请的空间了。

但我们应知道,一般来说,在C语言里,一般动态申请空间时,会这么写:

typeName* pointer_name = (typeName*)malloc(sizeof(typeName)*number);
if(pointer_name){//申请成功
	//业务处理
}
else{//申请失败
	//异常处理
}
	

也就是说在C语言里申请动态空间是否成功需要我们自己判断,然后处理。

但在C++里使用new,我们并不需要自己判断是否申请成功。这是因为new申请时会自己判断

·申请成功,成功直接返回地址,
·不成功,进行内存不足的处理模块,清理无用空间,继续申请,成功则返回地址,不成功则抛出异常。

是不是很nice!我们又能少写几行代码了!
在这里插入图片描述

使用delete释放动态数组

申请了动态数组,释放如下:

typeName* pointer_name = new typeName[number];
{//业务处理完成}
delete []pointer_name;//delete释放空间

看仔细了!delete []poimnter_name,释放目标之前有一个[]!!!。方括号告诉程序,要释放的目标是一个数组,不是一个元素!方括号里填不填number无所谓!你想填多少也无所谓!因为此处delete只会用到[],不管里面有没有数字/数字是多少

[Note]:
1.不要使用delete释放非new申请的内存空间
2.不要使用delete释放同一块空间两次
3.如果使用new分配空间,应使用delete释放
4.如果使用new[]分配空间,则应使用delete[]释放
5.对nullptr来说,delete用多少次都是安全的

使用new与delete为类的实例化对象管理空间

现有一个类T,我们想要申请可以存放number个T实例化后的空间,如下即可:

T* pointer_name = new T[number];

但为类实例化对象申请空间有以下两步:
第一步:调用operator new函数申请空间
第二步:在申请的空间上执行number次构造函数,完成number个对象的构造

释放空间如下即可:

T* pointer_name = new T[number];
{//业务处理}
delete []pointer_name;//delete释放空间

但为类实例化对象释放空间有以下两步:
第一步:在申请的空间上执行number次析构函数,完成number个对象的析构
第二步:调用operator delete函数释放空间

在这里new/delete与malloc/free的一些差别就有所体现了:
new/delete释放空间会调用构造/析构函数

malloc/free与new/delete的区别

比较项new/deletemalloc/free
申请空间所在内存区域
释放方式手动释放手动释放
是否可以初始化可以不可以
申请空间大小如何计算只需空间类型即可手动计算并传入
返回值是否需要强制类型转换不需要需要
申请失败返回值抛出异常NULL
申请自定义类型对象会调用构造/析构函数只开辟空间
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值