本篇内容主要讲解“C++的代码区、全局区、栈区和堆区是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++的代码区、全局区、栈区和堆区是什么”吧!
C++ 在程序执行时,将内存大致分为代码区,全局区,栈区和堆区四个区域。不同的区域存储不同的数据,赋予不同的生命周期,能够更灵活地进行编程。
代码区:存放函数体的二进制代码,由操作系统管理创建,代码区时共享的,对于频繁被执行的程序,只需要存有一份代码即可;
全局区:存放全局变量和静态变量以及常量,在程序结束后由操作系统释放;
栈区:由编译其自动分配释放,存放函数的参数值以及局部变量等;
堆区:一般由程序员通过 new 开辟空间,进行分配和释放,若程序员不释放,则程序结束时由操作系统回收
下面通过一个例子对全局区,栈区,堆区的数据声明周期进行说明:
// 全局变量属于全局区,由操作系统管理释放 int g_a = 1; int g_b = 2; int main(void) { cout << "g_a 的地址为: "<< int(&g_a) << endl; cout << "g_b 的地址为: " << int(&g_b) << endl; // 创建普通的局部变量,属于栈区 int a = 10; int b = 20; cout << "a 的地址为: " << int(&a) << endl; cout << "b 的地址为: " << int(&b) << endl; // 创建静态变量,属于全局区 static int s_a = 40; static int s_b = 50; cout << "s_a 的地址为: " << int(&s_a) << endl; cout << "s_b 的地址为: " << int(&s_b) << endl; // 程序员自己创建变量,属于堆区 int* d_a = new int(10); int* d_b = new int(20); cout << "d_a 的地址为: " << int(d_a) << endl; cout << "d_b 的地址为: " << int(d_b) << endl; }
输出结果为:
g_a 的地址为: 5300224 g_b 的地址为: 5300228
a 的地址为: 6421316 b 的地址为: 6421304
s_a 的地址为: 5300232 s_b 的地址为: 5300236
d_a 的地址为: 9547944 d_b 的地址为: 9547992
我们从中可以看到,g_a,g_b,s_a,s_b 都属于全局区,同理,a,b 都属于栈区,d_a,d_b 都属于堆区。由于栈区的数据在程序运行结束后会被编译器自动销毁,因此不要返回局部变量的地址,举例如下:
int* func() { int a = 10; // 栈区数据,在程序执行完之后自动释放 return &a; //虽然返回了a的地址,然而数据在func结束时已经被销毁 } int main(void) { int* a = func(); // 此时a表示在函数func在栈区开辟的地址,但是其中的数据已被销毁 cout << "a 的地址为: " << int(a) << "a 存放的数据为: " << *a << endl; cout << "a 的地址为: " << int(a) << "a 存放的数据为: " << *a << endl; }
输出结果为:
a 的地址为: 7601480a 存放的数据为: 10
a 的地址为: 7601480a 存放的数据为: 2084553696
由于编译器会对栈区的数据做一次保留,因此第一条的 cout 语句能够正常输出,然而第二次的输出才是内存地址 a 中的数据。
相反,堆区数据由程序员自己进行管理,在程序执行完之后并不会自动释放。当整个程序执行完毕之后会由操作系统释放。
int* func() { int * a = new int(10); // 程序员使用new在堆区开辟空间,在程序执行完之后自动释放 return a; //同样返回了a的地址,然而只要程序没有运行结束,除非程序员释放,否则会一直保留 } int main(void) { int* a = func(); // 此时a表示在函数func在堆区开辟的地址,编译器无法自动销毁 cout << "a 的地址为: " << int(a) << "a 存放的数据为: " << *a << endl; cout << "a 的地址为: " << int(a) << "a 存放的数据为: " << *a << endl; }
输出结果为:
a 的地址为: 23507016a 存放的数据为: 10
a 的地址为: 23507016a 存放的数据为: 10
1、栈区(stack):就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是函数的返回地址、参数、局部变量、返回值等,从高地址向低地址增长。在一个进程中,位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数的调用。其操作方式类似于数据结构中的栈。
2、堆区(heap): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,在程序运行过程中可以动态增加堆大小(移动break指针),从低地址向高地址增长。
堆:是操作系统所维护的一块特殊内存,它提供了动态分配的功能,当运行程序调用malloc()时就会从中分配,稍后调用free()可把内存交还。
自由存储区:自由存储是C++中通过new和delete动态分配和释放对象的抽象概念,通过new来申请的内存区域可称为自由存储区。基本上,所有的C++编译器默认使用堆来实现自由存储,也即是缺省的全局运算符new和delete也许会按照malloc和free的方式来被实现,这时藉由new运算符分配的对象,说它在堆上也对,说它在自由存储区上也正确。但程序员也可以通过重载操作符,改用其他内存来实现自由存储,例如全局变量做的对象池,这时自由存储区和堆区就有区别了。
3、数据区:主要包括静态全局区和静态区,如果要站在汇编角度细分的话还可以分为很多小的区。
全局区&静态区:全局变量和静态变量被分配到同一块内存中,在以前的 C 语言中,全局变量和静态变量又分为
全局初始化区(DATA段) :存储程序中已初始化的全局变量和静态变量
未初始化段(BSS段) :存储未初始化的全局变量和静态变量(局部+全局)。BSS段在DATA段的相邻的另一块区域。
BBS段特点:在程序执行前BBS段自动清零,所以未初始化的全局变量和静态变量在程序执行前已经成为0。
在 C++ 里面没有这个区分了,他们共同占用同一块内存区。
4、代码区:包括只读存储区和文本区,其中只读存储区存储字符串常量,就是常量区,文本区存储程序的机器代码。
其实“内存四区”和“内存五区”指的东西都是完全一样的
内存五区为:栈区、堆区、全局区(静态区)、常亮区、代码区
内存四区为:栈区、堆区、数据区(全局区(静态区)、常亮区)、代码区
因此从上面可以看出,对于内存四区而言,其只是把全局区(静态区)和常亮区合并为一个数据区而已,其实内容都是完全一样的
到此,相信大家对“C++的代码区、全局区、栈区和堆区是什么”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。