C++ 内存分区模型

目录

程序运行前

代码区

全局区

程序运行后

new

在堆区开辟数据 

delete释放堆区数据

堆区开辟数组

内存分区模型

栈(Stack)

堆(Heap)

全局/静态存储区(Global/Static Storage)

常量存储区(Constant Storage)

代码区(Code Area)


程序运行前

在程序编译后,生成了exe可执行程序,未执行该程序前分为两个区域

代码区

存放 CPU 执行的机器指令

代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可

代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令

全局区

全局变量和静态变量存放在此.

全局区还包含了常量区, 字符串常量其他常量也存放在此.

该区域的数据在程序结束后由操作系统释放

  • C++中在程序运行前分为全局区和代码区
  • 代码区特点是共享和只读
  • 全局区中存放全局变量、静态变量、常量
  • 常量区中存放 const修饰的全局常量  和 字符串常量
#include <iostream>
using namespace std;

//全局变量
int g_a = 10;
int g_b = 10;

//全局常量
const int c_g_a = 10;
const int c_g_b = 10;

int main() {

		//局部变量
		int a = 10;
		int b = 10;


		//静态变量
		static int s_a = 10;
		static int s_b = 10;

	return 0;
}

程序运行后

不要返回局部变量的地址,栈区开辟的数据由编译器自动释放

#include <iostream>
using namespace std;

int * func(int a) // 形参也是放在栈区
{
	int a = 10;
	return &a; // 不要返回局部变量的地址,栈区开辟的数据由编译器自动释放
}

int main() {

	int *p = func();

	cout << *p << endl; // 10 第一次可以打印这个数字,是因为编译器做了保留
	cout << *p << endl; // 随机值 第二次这个数据就不再保留了
	 
	return 0;
}

new

利用new关键字,可以将数据开辟到堆区

在堆区开辟数据 

int *p = new int(10)

new int(10)表示在堆内存上动态分配了一个int类型的空间,并用值10初始化了该空间。
p指针变量,本质上也是局部变量,放在栈上,指针指向的是所开辟的堆内存区的数据的地址。

int *p = func()

p虽然是在func()函数中声明的局部变量,但它存储的是一个指向堆内存的地址。
当函数func()执行完毕后,p虽然在函数栈帧中被销毁,但指向堆内存的地址仍然存在。

int * func() {
	/*
		利用new关键字,可以将数据开辟到堆区
	*/
	int *p = new int(10); // new当前返回的是int类型的指针,具体什么类型由开辟的数据类型决定
	return p; // 客观上返回的是堆区的地址
}

int *p = func()

/*
	p虽然是在func()函数中声明的局部变量,但它存储的是一个指向堆内存的地址。
	当函数func()执行完毕后,p虽然在函数栈帧中被销毁,但指向堆内存的地址仍然存在。
*/
cout << *p << endl; // 10

delete释放堆区数据

    int * func() {
	    int *p = new int(10); 
	    return p; 
    }

	int *p = func();
	delete p; // 释放堆区数据
	cout << *p << endl; // error 内存已经释放,再次访问已经是非法操作,报错

堆区开辟数组

在堆区开辟数组——创建10个整形数据的数组

  • new int[10]动态分配一个包含10个int类型元素的数组时,内存管理系统会分配一块连续的内存空间来存储这个数组。
  • 指针arr存储的就是这块内存空间的起始地址,也就是数组的第一个元素的地址。
  • 类似于C语言中的数组名
void test() {
	/*
		new int[10]动态分配一个包含10个int类型元素的数组时,内存管理系统会分配一块连续的内存空间来存储这个数组。
		指针arr存储的就是这块内存空间的起始地址,也就是数组的第一个元素的地址。
		类似于C语言中的数组名
	*/
	int *arr = new int[10]; // 10代表数组有10个元素,注意这里是中括号,不是小括号
	for (int i = 0; i < 10; i++)
	{
		arr[i] = i + 100; // 给这10个元素赋值 1000~109 (arr[i] == *(arr + i))
	}
	for (int i = 0; i < 10; i++)
	{
		cout << arr[i] << endl; // 100 ~ 109
	}

	//释放堆区的数组数据内存。数组需要加 []
	delete[] arr;
}


test();

内存分区模型

C++的内存分区模型描述了程序在运行时如何使用系统内存。了解内存分区模型对于理解程序的内存管理和运行效率非常重要!

在一般情况下,C++程序在内存中的布局可以分为以下几个主要区域:

栈(Stack)

  1. 栈是用于存储局部变量、函数参数、函数返回地址以及函数调用时所需的临时数据的区域。
  2. 栈的大小在程序运行时是可以动态变化的,通常由系统自动管理。
  3. 栈内存的分配和释放是由系统自动完成的,遵循"先进后出"的原则。

堆(Heap)

  1. 堆被用于存储动态分配的内存,例如使用newdelete关键字来分配和释放的内存。
  2. 堆的大小也是动态变化的,可以在程序运行时根据需要进行分配和释放。
  3. 程序员通常需要手动管理堆内存的分配和释放,因此在使用时需要注意内存泄漏和内存溢出的风险。

全局/静态存储区(Global/Static Storage)

  1. 全局变量、静态变量以及常量通常存储在这个区域。
  2. 这部分内存在程序启动时就被分配,并在程序结束时才被释放,它们的生命周期与整个程序的生命周期相同。

常量存储区(Constant Storage)

  1. 存放常量数据,如字符串常量等。
  2. 这部分内存通常被固定分配,并且存储的数据在程序运行期间不会改变。

代码区(Code Area)

  1. 存放程序的执行代码,通常是只读的。
  2. 程序的机器指令和函数体都存储在这个区域。
  • 30
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

山楂树の

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

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

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

打赏作者

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

抵扣说明:

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

余额充值