C++ 内存分区

原创文章,转载请注明出处。

C++ 内存分区

C++ 内存分区:栈、堆、全局/静态存储区、常量存储区、代码区。

栈: 存放函数的局部变量、函数参数、返回地址等,由编译器自动分配和释放。

堆: 动态申请的内存空间,就是由 malloc 分配的内存块,由程序员控制它的分配和释放,如果程序执行结束还没有释放,操作系统会自动回收。

全局区/静态存储区(.bss 段和 .data 段): 存放全局变量和静态变量,程序运行结束操作系统自动释放,在 C 语言中,未初始化的放在 .bss 段中,初始化的放在 .data 段中,C++ 中不再区分了。

常量存储区(.data 段): 存放的是常量,不允许修改,程序运行结束自动释放。

代码区(.text 段): 存放代码,不允许修改,但可以执行。编译后的二进制文件存放在这里。


说明:
从操作系统的本身来讲,以上存储区在内存中的分布是如下形式(从低地址到高地址):.text 段 --> .data 段 --> .bss 段 --> 堆 --> unused --> 栈 --> env

代码实战:

#include <iostream>
using namespace std;

/*
说明:C++ 中不再区分初始化和未初始化的全局变量、静态变量的存储区,如果非要区分下述程序标注在了括号中
*/

int g_var = 0; // g_var 在全局区(.data 段)
char *gp_var;  // gp_var 在全局区(.bss 段)

int main()
{
    int var;                    // var 在栈区
    char *p_var;                // p_var 在栈区
    char arr[] = "abc";         // arr 为数组变量,存储在栈区;"abc"为字符串常量,存储在常量区
    char *p_var1 = "123456";    // p_var1 在栈区;"123456"为字符串常量,存储在常量区
    static int s_var = 0;       // s_var 为静态变量,存在静态存储区(.data 段)
    p_var = (char *)malloc(10); // 分配得来的 10 个字节的区域在堆区
    free(p_var);
    return 0;
}

堆和栈和有什么区别?

申请方式不同:
栈是系统自动分配,堆是程序员主动申请。

申请后系统响应:
分配栈空间,如果剩余空间大于申请空间则分配成功,否则分配失败栈溢出;
申请堆空间,堆在内存中呈现的方式类似于链表(记录空闲地址空间的链表),在链表上寻找第一个大于申请空间的节点分配给程序,将该节点从链表中删除,大多数系统中该块空间的首地址存放的是本次分配空间的大小,便于释放,将该块空间上的剩余空间再次连接在空闲链表上。

内存排布不同:
栈在内存中是连续的一块空间(向低地址扩展)最大容量是系统预定好的,
堆在内存中的空间(向高地址扩展)是不连续的。

申请大小的限制不同:
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。意思是栈顶的地址和栈的最大容量是系统预先规定好的,在Windows下,栈的大小是 2M (也有的说是 1M ,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

申请效率不同:
栈是有系统自动分配,申请效率高,但程序员无法控制;
堆是由程序员主动申请,效率低,使用起来方便但是容易产生碎片。

存放的内容不同:
栈中存放的是局部变量,函数的参数;
堆中存放的内容由程序员控制。

存取效率不同:

char s1[] = /"a/";
char *s2 = /"b/";

比如上面的代码中:
a 是在运行时刻赋值的;
b 是在编译时就确定的;
但是,在以后的存取中,在栈上的数组比指针所指向的字符串 ( 例如堆 ) 快。 比如:

int main()
{
    char a = 1;
    char c[] = /"1234567890/";
    char *p =/"1234567890/";
    a = c[1];
    a = p[1];
    return 0;
}

第一种在读取时直接就把字符串中的元素读到寄存器 cl 中,而第二种则要先把指针值读到 edx 中,再根据 edx 读取字符,显然慢了。

综上,堆和栈的主要区别我们就明白了: 做一个比喻:
使用栈就像我们去饭馆里吃饭,只管点菜(申请)、付钱、吃(使用),吃完了就走,不用理会这个过程,比如切菜、洗菜以及洗碗等扫尾工作,好处是快捷,但是自由度小。
使用堆,就像是自己动手做喜欢吃的菜肴,需要自己动手,但是比较符合自己的口味,而且自由度大。

谢谢,创作不易,大侠请留步… 动起可爱的双手,来个赞再走呗 <( ̄︶ ̄)>

  • 44
    点赞
  • 136
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WhiteTian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值