[c++]new和malloc的细节

  • New和malloc的区别
  • new是操作符,malloc是函数
  • New不需要包含头文件,不需要判空,不用强转,new出来的空间直接初始化
  • 在类里:Malloc不会调构造,只是开辟一块类类型大小的空间,free也不会调用析构.new会调构造函数,指针会指向堆上的一个对象.delete会调析构
  • New里调用了malloc,如果没申请成功,会循环申请.
  • New先调用operator new函数,这个函数里调用了malloc,申请成功后返回指针,然后调用类的初始化函数,这是申请一个类.要是申请多个类,调用的是operator new[]函数,这个里面调用的是operater new函数
  • Delete会调用一个库里的函数,这个函数里先调用析构函数清理资源,再调用operator delete函数释放空间这个函数里还是调用free释放空间的...如果是delete[],调用的是operater delete[]里调用operater delete
  • 先构造全局对象,在构造局部静态对象,最后才构造普通对象,
  • new一个对象delete只析构一次.new连续10个对象,调用delete只析构一次,调用delete[]才会析构10次
  • 频繁的申请空间和释放空间,容易造成内存碎片,甚至内存泄漏,栈区由于是自动管理,不存在此问题
  • 栈可以通过函数_alloca进行动态分配
  • char* p = new char[100]申请一段内存,然后使用delete p释放.内置类型不会报错,类类型就会报错了.不建议这么用
  • malloc申请的内存比你想要的大,看malloc底层原理(多申请了一个结构体,下来是想要的空间,最后是一个四字节的保护机制,)结构体里有双向链表,操作系统用双向链表管理malloc出去的空间。。。malloc返回的时候是想要部分的开始地址,free的时候会往回偏,把多申请的结构体也释放掉
  • new操作符:就是new
  • 操作符new: 是函数,程序员可以自己实现。就是new调用的operator new函数,operator delete也类似。但是自己写的operator new会调用构造函数,operator delete不会调用析构函数(一般不用)
  • placement-new或者定位new:解决malloc出来的空间没有调用构造函数的问题 malloc执行完后执行new(【指针】)【类】在固定的位置进行构造 ,加new()【】的原因是,编译器看到new就会调用operator new函数(这个operater new是两个参数,和上面的不一样),再调用构造函数。。。free之前程序员可以调用析构函数。但是构造时程序员是不能调用的。
  • _CrtDumpMemoryLeaks();程序运行结束后会显示泄露了多少内存
  • 内存泄漏危害:
  • 堆栈的区别:
  • (1)管理方式不同。栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏;
  • (2)空间大小不同。每个进程拥有的栈大小要远远小于堆大小。理论上,进程可申请的堆大小为虚拟内存大小,进程栈的大小 64bits 的 Windows 默认 1MB,64bits 的 Linux 默认 10MB;
  • (3)生长方向不同。堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低。
  • (4)分配方式不同。堆都是动态分配的,没有静态分配的堆。栈有 2 种分配方式:静态分配和动态分配。静态分配是由操作系统完成的,比如局部变量的分配。动态分配由alloca()函数分配,但是栈的动态分配和堆是不同的,它的动态分配是由操作系统进行释放,无需我们手工实现。
  • (5)分配效率不同。栈由操作系统自动分配,会在硬件层级对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是由C/C++提供的库函数或运算符来完成申请与管理,实现机制较为复杂,频繁的内存申请容易产生内存碎片。显然,堆的效率比栈要低得多。
  • (6)存放内容不同。栈存放的内容,函数返回地址、相关参数、局部变量和寄存器内容等。当主函数调用另外一个函数的时候,要对当前函数执行断点进行保存,需要使用栈来实现,首先入栈的是主函数下一条语句的地址,即扩展指针寄存器的内容(EIP),然后是当前栈帧的底部地址,即扩展基址指针寄存器内容(EBP),再然后是被调函数的实参等,一般情况下是按照从右向左的顺序入栈,之后是被调函数的局部变量,注意静态变量是存放在数据段或者BSS段,是不入栈的。出栈的顺序正好相反,最终栈顶指向主函数下一条语句的地址,主程序又从该地址开始执行。堆,一般情况堆顶使用一个字节的空间来存放堆的大小,而堆中具体存放内容是由程序员来填充
  • 栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
  • 堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,
  • 会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表
  • 中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的
  • 首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。
  • 另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部
  • 分重新放入空闲链表中。
  • 2.3申请大小的限制
  • 栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意
  • 思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有
  • 的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将
  • 提示overflow。因此,能从栈获得的空间较小。
  • 堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储
  • 的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小
  • 受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值