千家信息网

C++的代码区、全局区、栈区和堆区是什么

发表于:2024-11-22 作者:千家信息网编辑
千家信息网最后更新 2024年11月22日,本篇内容主要讲解"C++的代码区、全局区、栈区和堆区是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"C++的代码区、全局区、栈区和堆区是什么"吧!C+
千家信息网最后更新 2024年11月22日C++的代码区、全局区、栈区和堆区是什么

本篇内容主要讲解"C++的代码区、全局区、栈区和堆区是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"C++的代码区、全局区、栈区和堆区是什么"吧!

C++内存四区

C++ 在程序执行时,将内存大致分为代码区,全局区,栈区和堆区四个区域。不同的区域存储不同的数据,赋予不同的生命周期,能够更灵活地进行编程。

  1. 代码区:存放函数体的二进制代码,由操作系统管理创建,代码区时共享的,对于频繁被执行的程序,只需要存有一份代码即可;

  2. 全局区:存放全局变量和静态变量以及常量,在程序结束后由操作系统释放;

  3. 栈区:由编译其自动分配释放,存放函数的参数值以及局部变量等;

  4. 堆区:一般由程序员通过 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++的代码区、全局区、栈区和堆区是什么"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

0