参考自:
[1] https://www.cnblogs.com/xuelisheng/p/9278800.html
[2] https://www.cnblogs.com/findumars/p/5929831.html?utm_source=itdadao&utm_medium=referral
[2] 对于 c++ 中内存的管理讨论得很深入。
1. 静态储存区,储存全局变量,常量。程序编译时即分配好,程序运行结束时自动释放。
2. 栈区,非常有限的一块内存区域,储存局域变量,函数调用结束之后自动释放。因为“栈内存分配运算内置于处理器的指令集中”,所以(按我理解)这块内存的分配和计算都很快。
但是栈区很小,可以用下面的代码测试得到。(参考自:[3] https://blog.csdn.net/boyixuanbo/article/details/52864954)
#include<iostream> using namespace std; long int count = 0; void stack(){ char msg[1024]; cout<<"count="<<++count<<endl; stack(); } int main(void){ stack(); return 0; }
输出为:
count=1
...
count=7939
Segmentation fault (core dumped)
最终是栈溢出。stack() 每运行一次就申请 1024 byte,所以总共申请了 7939 k,即不到 8 M 以后,栈就爆了。说明栈区大小不到 8 M。
栈内存从高地址向低地址生长。
3. 堆区
new 或者 new [] 开辟的动态内存,都在堆区,堆区几乎可以穷尽电脑所有内存。开辟的动态内存需要程序员用代码 delete 或者 delete [] 进行删除,否则在程序结束之前一直占用,程序结束之后系统自动回收。另外,new [] 申请到的内存不一定连续,因为可能堆区有些内存块被占用。
“频繁 new 和 delete 势必会导致堆内存空间不连续,造成大量碎片,使程序效率降低”(unchecked)。
“但当你必须要使用new 和delete时,你不得不控制C++中的内存分配。你需要用一个全局的new 和delete来代替系统的内存分配符,并且一个类一个类的重载new 和delete。
一个防止堆破碎的通用方法是从不同固定大小的内存持中分配不同类型的对象。对每个类重载new 和delete就提供了这样的控制。”
[2] 中有重载 new 和 delete 的代码。
堆内存从低地址向高地址生长
为什么有malloc/free 还需要 new/delete?因为 malloc/free 不能自动为 对象(非内部数据)申请动态内存,而 new/delete 可以自动调用 对象的构析函数进行申请和释放。
4. 自由储存区(我从来没有涉及过)
malloc() 开辟出来的内存,需要 free() 来终止生命,与堆区相似。
5. 常量储存区
不可改变的常量储存在这里,不允许修改。