C++内存分区模型

C++程序在执行时,将内存大方向划分为4个区域

代码区:存放函数体的二进制代码,所有代码都会放入这个区,由操作系统进行管理的

全局区:存放全局变量和静态变量以及常量

栈区:由编译器自动分配释放, 存放函数的参数值,局部变量等

堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收

内存四区意义:

不同区域存放的数据,赋予不同的生命周期, 给我们更大的灵活编程

一、程序运行前

在程序编译后,生成了 exe 可执行程序, 未执行该程序前 分为两个区域
代码区:
存放 CPU 执行的机器指令
代码区是 共享 的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可
代码区是 只读 的,使其只读的原因是防止程序意外地修改了它的指令

为什么需要这两个特点?

  1. 只读:避免程序运行时动态修改指令导致不可预测行为(如病毒注入)、提高稳定性,确保代码逻辑的一致性。

  2. 共享:减少重复代码的内存占用(尤其对系统级程序如 libc 库)、提升多进程环境的效率(如 Web 服务器启动多个 worker 进程)。

全局区:
全局变量和静态变量存放在此 .
全局区还包含了常量区 , 字符串常量和其他常量也存放在此 .
该区域的数据在程序结束后由 操作系统 释放
示例:
//全局变量
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;
//打印地址
cout << "局部变量a地址为: " << (int)&a << endl;
cout << "局部变量b地址为: " << (int)&b << endl;
cout << "全局变量g_a地址为: " << (int)&g_a << endl;

cout << "全局变量g_b地址为: " << (int)&g_b << endl;
//静态变量
static int s_a = 10;
static int s_b = 10;
cout << "静态变量s_a地址为: " << (int)&s_a << endl;
cout << "静态变量s_b地址为: " << (int)&s_b << endl;
//字符串常量
cout << "字符串常量地址为: " << (int)&"hello world" << endl;
cout << "字符串常量地址为: " << (int)&"hello world1" << endl;
cout << "全局常量c_g_a地址为: " << (int)&c_g_a << endl;
cout << "全局常量c_g_b地址为: " << (int)&c_g_b << endl;
const int c_l_a = 10;
const int c_l_b = 10;
cout << "局部常量c_l_a地址为: " << (int)&c_l_a << endl;
cout << "局部常量c_l_b地址为: " << (int)&c_l_b << endl;
system("pause");
return 0;
}

  

总结:

全局区(数据区)中存放: 全局变量、静态变量

常量区中存放:  const修饰的全局变量(全局常量)、字符串常量。(只读区)

存放在栈区:const修饰的局部变量(局部常量)、局部变量。                   

       高地址

         栈区

       (Stack)

   ← 局部变量、局部常量(如 `int x`, `const int y`)

          地址:0x7ffd... → 0x7ffc...(向低增长)

        堆区

       (Heap)    

  ← `malloc`/`new` 动态分配(地址无固定规律)

       数据区

    (Data/BSS) 

  ← 全局变量、静态变量(如 `g_var`, `s_local`)

地址:0x601044...

     只读数据区 

     (RO Data)

   ← 字符串常量、全局常量(如 `"Hello"`, `G_CONST`)
        地址:0x4006d4...

      代码区

       (Text)   

程序指令(如 `main()` 的机器码)

地址:0x400000...

      底地址

二、程序运行后

栈区:

由编译器自动分配释放, 存放函数的参数值,局部变量、形参等

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

示例:

int * func()
{
int a = 10;
return &a;
}
int main() {
int *p = func();
cout << *p << endl;//第一次可以正确打印是因为编译器帮忙给数据做了一次保留
cout << *p << endl;//第二次出现乱码,编译器已经释放数据
system("pause");
return 0;
}

堆区:

由程序员分配释放,若程序员不释放,程序结束时由操作系统回收

C++中主要利用new在堆区开辟内存

示例:

int* func()
{
int* a = new int(10);
return a;
}
int main() {
int *p = func();
cout << *p << endl;
cout << *p << endl;
system("pause");
return 0;
}

C语言中的开辟动态内存方式:    int * p=(int *)malloc(sizeof(int));

C++语言中的开辟动态内存方式:int * p=(int *)new int(x);

总结:

堆区数据由程序员管理开辟和释放

堆区数据利用new关键字进行开辟内存

new操作符

C++中利用new操作符在堆区开辟数据

堆区开辟的数据,由程序员手动开辟,手动释放,释放利用操作符 delete

语法: new 数据类型

利用new创建的数据,会返回该数据对应的类型的指针

示例1: 基本语法

#include <iostream>
using namespace std;
//任务一:在堆中开辟一个int数据空间
int* func_01()
{
	int* p = new int(10);
	return p;
}
int main()
{
	int* p = func_01();
	cout << *p << endl;//不管打印多少个都是显示原始数据
	cout << p << endl;//显示的是原始堆地址
	delete p;
	cout << p << endl;//显示的是乱码,说明已经释放空间
	system("pause");
	return 0;
}
示例 2 :开辟数组
#include <iostream>
using namespace std;
//任务二:在堆中开辟一个int数组空间
int* func_02()
{
	int* arr = new int[10];
	for (int i = 0; i < 10; i++)
	{
		arr[i] = i + 10;
	}
	for (int i = 0; i < 10; i++)
	{
		cout << arr[i] << endl;
	}
	return arr;
}

int main()
{
	int* arr = func_02();
	delete[] arr;//释放数组要加[]

	system("pause");
	return 0;
}


         

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值