C/C++动态内存管理

 

 

程序内存分配区域:

(1)栈区:栈区主要存放执行函数而分配的局部变量、函数形参、返回数据、返回地址等。效率很高。

(2)堆区。程序员申请与释放。程序结束时可能由os回收,分配方式类似链表。

(3)静态区(数据段)。存放全局变量、静态数据。程序结束后由系统释放。

(4)代码段(常量去)。存放函数体的二进制代码(全局函数、类成员函数)

关于C中的动态内存管理:

(1)void *malloc(size_t size);//向内存申请一块连续可用的空间,并返回指向这块空间的指针,开辟失败返回NULL。指定大小为size个字节。

(2)void free(void* ptr);//动态内存的释放,一般释放后再将指针置空.若ptr指向的空间不是动态开辟的,free行为未定义,如果ptr是NULL指针,则函数什么事情也不做。

(3)void* calloc(size_t num, size_t size);//开辟一块num个大小为size的空间,并且将空间中每个字节初始化为0.

(4)void* realloc(void* ptr, size_t size);//将以ptr为起始地址的内存,重新调整大小为size个字节。它在调整内存大小时有两种情况(1)原有空间之后有足够大的空间。扩展内存的方法是直接追加内存,原来空间数据不发生变化(2)原有空间之后没有足够大的空间。在堆空间上另找一个大小合适的连续空间,然后函数返回新空间的地址(原来的空间realloc完成,不要我们操心)。需要注意:扩展内存时,先用一个临时指针变量来接收realloc()的返回值,而不是直接将返回值赋给要扩展内存的起始地址,因为如果扩展内存失败返回NULL指针,那么会将原来内存的起始位置覆盖掉。

关于C++中的动态内存管理:

1.new/delete操作符

new/delete操作内置类型:

new/delete对于内置类型来说和malloc/free基本类似,区别在于new可以初始化。如int* p=new int(4).

new/delete操作自定义类型:

new会做两件事:

(1)调用operator new()开空间,operator new()是一个全局的函数,可以被重载,其实operator new()底层又调用的是malloc()函数。那既然new在最底层还是调用了malloc开的空间,为什么这么麻烦呢?原因是operator new()在调用malloc()的同时还做了其它的操作,比如说,之前在C中malloc()失败后会返回NULL,并且设置errno,但是operator new()失败后会做的操作是,尽量再去向系统请求内存,实在分配不就抛一个bad_alloc异常出来。

(2)调用构造函数。

delete也会做两件事情:

(1)先调用析构函数,将对象中的资源释放掉。

(2)调用operator delete()释放空间,operator delete[]也是一个全局的函数,而operator delete[]在底层又调用了free().这里注意delete一个空指针是没有问题的,它只是什么都不做而已。

2.new[]/delete[]操作符

new[]/delete[]操作内置类型:

和malloc/free类似。

new[]/delete[]操作自定义类型:

new[N]也会做两件事:

(1)调用operator new[]函数,operator new[]又会去调用operator new()函数申请N个对象的空间(当有显示的析构函数时,这里会多开4字节的空间,用来存储对象的个数N,不然析构函数不知道要析构多少次),而operator new()函数又会去调用malloc()函数。

(2)在申请的空间时调用N次构造函数。

delete[N]也会做两件事情

(1)调用N次析构函数,释放每个对象中的资源,注意后创建的对象先析构。(这里的N就是开辟空间时最前面多开辟出空间的地址,假如指向这个空间的指针是pt,

那么这样拿到这个值:*(int*((int)pt-4)),因为堆空间是向上增长的。

(2)最后调用operator delete[]函数,operator delete[]调用operator delete()函数,operator delete()调用free()释放空间。

注意:malloc/free new/delete new[]/delete[]一定要匹配使用。否则内置类型可能没啥问题,因为不用调用构造函数和析构函数,但是对于自定义类型,可能发生内存泄漏、崩溃现象。

定位new表达式:

如果Test是个类, Test* p=(Test*)malloc(sizeof(Test));这里的p指向的空间只是一个Test类对象的大小,但是它只是一块空间,而不是一个对象,因为malloc只负责开空间,不向new一样还调用构造函数初始化对象。这时候我们可以用new(p) Test;进行对p指向的空间进行初始化一个对象,这时候p指向的就是一个Test对象。这时候我们如何释放空间呢?用malloc的话,掉不到析构函数清理资源,用delete的话与申请时不匹配,这时候我们显示的调用该对象的析构函数,即pt->~Test().

另外需要注意的是:如果Test* pt=new Test[10];即申请连续的自定义类型空间,必须提供默认的构造函数,因为这样需要调用默认构造函数来初始化对象的。

那么,malloc/free和new/delete的区别是什么?

共同点:

默认都是从堆上申请空间,并且需要手动释放的。(当然new中的operator new可以自定制申请空间的地方)

不同点:

(1)malloc/free是C中的函数,而new/delete是C++中的操作符

(2)malloc只开空间,不初始化,而new可以初始化

(3)malloc需要传递申请空间的大小,new只需要加上类型即可

(4)malloc的返回类型是void*,具体使用时需要根据接受类型强转,而new不需要,直接由空间的类型

(5)malloc申请空间失败时,返回NULL,new反复尝试后失败会抛异常

(6)申请自定义类型对象时,malloc/free只负责开空间,释放空间,不会调用构造函数、析构函数进行初始化对象、清理对象所管理的资源。

(7)new/delete在底层调用了malloc/free

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值