c++内存管理

1.内存分段问题

栈:又叫做堆栈,非静态局部变量/函数参数/返回值,栈是向下增长的

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

堆:用于程序运行中动态内存分配,堆是向上增长的;

数据段:存储全局数据和静态数据

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

2.c中动态内存开辟

适合场景:长度在程序运行时才知道数组分配内存空间

为什么使用动态内存开辟:

1.如果数组的空间小于存放数据大小;

2.数组过大,数据较小,内存浪费;

3.输入数据大于数组大小,程序无法给出正常的应答;

malloc/calloc/realloc/free四个函数进行动态内存(内存池)的管理;

1.void *malloc(size_t size)

(1)参数:开辟内存字节数

返回:成功返回一个指向开辟空间起始地址位置的指针

失败返回NULL;

2.void *calloc(size_t num, size_t size)

(1)参数:num 元素数量; size 每个元素所占字节

返回:成功返回指向开辟的空间的首地址的指针(返回之前初始化为0)

失败返回NULL

3。void *realloc(void *pointer ,size_t new_size)

(1)参数:pointer指向空间的首元素地址的指针;开辟空间字节数

返回:成功返回指针,失败返回NULL;

区别:在动态开辟的空间进行增加

(1)在原来的空间上进行增加(返回原来的指针),不初始化

(2)原来内存无法改变大小,重新开辟空间,复制原来的到新的地址,返回新指针,释放原来的空间;

4.void free(void *pointer)

参数:释放空间的指针

动态开辟开辟的空间返回值,一定要进行判空

动态内存开辟常见错误:

1.堆NULL进行解引用操作

2.动态内存访问存在越界

3.对非动态开辟内存free

4.对一块动态开辟空间重复释放

5.释放动态开辟内存一部分

6.动态开辟内存没有释放(内存泄露)

3.c++中内存管理

通过new和delete运算符进行动态内存的管理(开辟空间不需要判空)

eg : int *pl1=new int ; //开辟单个整形空间

int *pl2=new int(10); //初始化

开辟:new +类型 释放 :delete +类型

eg : int *pl3=new int[10]; //开辟连续空间

开辟:new+类型[ ] 释放 delete[ ] +pl3

匹配问题:

new开辟空间,free释放。,不会调用析构函数

如果开辟,释放不匹配,不会调用构造函数,delete会构造出错

内存泄露,代码崩溃:

delete [ ]去释放非new [ ]开辟的空间;

new[ ]开辟的空间没有用delete [ ]释放;

new :

1.申请空间:调用 void *operator new(size_t size)

调用malloc循环申请,直到申请成功,

成功返回地址

失败:检查是否有内存不足应对措施

有:继续malloc

没有:提供异常

2.调用构造函数:初始化对象

delete:

1.调用析构函数:将指针所指向的资源清理掉;

2.释放空间:

调用 void *operator delete(void *p)

调用free释放

new [ ]:

1.申请空间: void *operator new [ ](size_t count=N*sizeof(t)+4(存放开辟对象个数,目的:调用多次析构函数))

operator new (count)

调用malloc循环申请,直到申请成功,

成功返回地址

失败:检查是否有内存不足应对措施

有:继续malloc

没有:提供异常

2.调用N次构造函数为每个对象初始化:

delete[ ]:

1.销毁对象:

a.从空间前四个字节取出析构函数的调用次数N;

b.调用N次析构函数来析构它的N个对象;

2.释放空间:

调用 void *operator delete[ ](void *p)

operator delete p

free p

4定位new表达式:

定义:在已经分配的原始内存空间中调用一个构造函数初始化一个对象

定位new表达式:

new (place_address)type

new(place_address)type(initilizer_list)

place_address必须是一个指针initilizer_list是类型的初始化列表中定位new表达式的实际调用;

使用场景:多用于对象池化处理。

对象池化:将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用,从而在一定程度减少了创建对象造成的开销,而保存对象的容器被称为“对象池”

5.malloc/free&new/delete的区别和联系

直接调用malloc的缺陷:1,系统需要提供分配算法,效率低;

2,额外的空间;

3,内存碎片;

4,内存泄露;

解决:内存池分配

区别: 1. 内存申请的位置:

malloc函数是从堆上分配内存

new(自由存储区)默认在堆上,一般取决于operator new决定位置;

2.成功返回类型:

malloc成功返回void *,需要通过强制类型把void*转换成需要类型

new 成功时返回对象类型的指针,类型与对象匹配,不需要转换,所以new时符合安全类型的操作符

3.失败返回类型 :

malloc 返回NULL

new 返回bac_alloc异常

4.是否需要指定内存大小:

malloc 需要显示指出需要的内存大小

new不需要,编译器会根据类型自动计算

5.是否调用构造函数和析构函数:

malloc不调用构造和析构函数

new需要调用构造函数,delete会调用析构函数

6.对数组处理方式:

malloc直接开辟,如果要动态分配数组,需要手动定义

new分别调用每一个构造函数初始化每个数组元素,释放时调用析构函数,一一对应。

7.是否可以互相调用:

malloc不能调用new

new(operator new &operator delete 需要调用malloc)

8.是否可以被重载:

malloc&free不允许被重载

new中operator new &operator delete可以被重载

9.能直观分配内存:

malloc使用发现不够可以realloc扩充

new不能实现内存的扩充

10.客户处理内存分配不足:

malloc客户不能去编程决定内存不足分配时要干什么,只能返回NULL;

new在operator new抛出异常之前会调用一个用户指定错误处理函数new-handler,它是指针,指向一个没有参数没有返回值的函数,即错误处理函数为了处理错误,客户需要调用set_new_handler,这是一个库函数,参数new_handlerdr指针,指向了operator new无法分配时调用的函数,返回值也是指针,指向set_new_handler被调前正在执行的new-handler函数。

11.类型

malloc/free是标准库函数;

new/delete是c++操作符;

6.特殊要求设计类

1.只能在堆上创建对象;

2.只能在栈上创建对象;

3.类只能创建一个对象;

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值