C++ 内存分区模型

目录

程序运行前

代码区

全局区

程序运行后

new

在堆区开辟数据

delete释放堆区数据

堆区开辟数组

内存分区模型

栈(Stack)

堆(Heap)

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

[常量存储区(Constant Storage)](#常量存储区(Constant Storage))

[代码区(Code Area)](#代码区(Code Area))


程序运行前

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

代码区

存放 CPU 执行的机器指令

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

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

全局区

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

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

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

  • C++中在程序运行前分为全局区和代码区
  • 代码区特点是共享和只读
  • 全局区中存放全局变量、静态变量、常量
  • 常量区中存放 const修饰的全局常量 和 字符串常量
cpp 复制代码
#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;
}

程序运行后

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

cpp 复制代码
#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虽然在函数栈帧中被销毁,但指向堆内存的地址仍然存在。

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

int *p = func()

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

delete释放堆区数据

cpp 复制代码
    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语言中的数组名
cpp 复制代码
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. 程序的机器指令和函数体都存储在这个区域。
相关推荐
Dream_Snowar22 分钟前
速通Python 第三节
开发语言·python
唐诺32 分钟前
几种广泛使用的 C++ 编译器
c++·编译器
高山我梦口香糖1 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
冷眼看人间恩怨2 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
信号处理学渣2 小时前
matlab画图,选择性显示legend标签
开发语言·matlab
红龙创客2 小时前
某狐畅游24校招-C++开发岗笔试(单选题)
开发语言·c++
Lenyiin2 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
jasmine s2 小时前
Pandas
开发语言·python
biomooc2 小时前
R 语言 | 绘图的文字格式(绘制上标、下标、斜体、文字标注等)
开发语言·r语言
骇客野人2 小时前
【JAVA】JAVA接口公共返回体ResponseData封装
java·开发语言