C++学习笔记(14)—— 内存分区模型
C++程序在执行时,将内存大致分为4个区域。
- 代码区:存放函数体的二进制代码,由操作系统进行管理
- 全局区:存放全局变量和静态变量以及常量
- 栈区 :由编译器自动分配释放,存放函数的参数值,局部变量等
- 堆区 :由程序员分配和释放,若程序员不释放,程序结束时由操作系统释放回收
内存四区的意义:
不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活编程
1.1、程序运行前
在程序编译后,生成了exe可执行程序,未执行该程序前分为两个区域:
- 代码区:
- 存放cpu执行的机器指令
- 代码区是共享的,共享的目的是对于频繁操作被执行的程序,只需要在内存中有一份代码即可
- 代码区是只读的,使其只读的原因是防止程序意外地修改了他的指令
- 全局区:
- 全局变量和静态变量存放在此
- 全局区还包含了常量区(字符串常量和其它常量(const))
- 全局区的数据在程序执行结束后由操作系统系释放
eg:
#include <iostream>
using namespace std;
//全局区/静态变量、常量
//创建全局变量 在函数体外创建的变量
int p_a = 10;
int p_b = 11;
//const修饰的全局变量
const int cp_a = 10;
const int cp_b = 11;
int main()
{
cout << "全局区练习:" << endl << endl;
//创建普通局部变量 (在函数体内的变量都是局部变量)
int a = 10;
int b = 11;
//查看局部变量在内存中的地址
cout << "局部变量a的地址是:" <<(int) &a << endl;
cout << "局部变量b的地址是:" << (int)&b << endl;
cout << "两个局部变量相差:" << (int)&a-(int)&b<< " 个字节" << endl << endl;
//查看全局变量在内存中的地址
cout << "全局变量p_a的地址是:" << (int)&p_a << endl;
cout << "全局变量p_b的地址是:" << (int)&p_b << endl;
cout << "两个全局变量相差:" << (int)&p_a - (int)&p_b << " 个字节" << endl << endl;
//静态变量 在普通变量前加 static,就属于静态变量
static int g_a = 10;
static int g_b = 11;
cout << "静态变量p_a的地址是:" << (int)&g_a << endl;
cout << "静态变量p_b的地址是:" << (int)&g_b << endl;
cout << "两个静态变量相差:" << (int)&g_a - (int)&g_b << " 个字节" << endl << endl;
//静态常量 在普通变量前加 static const,就属于静态变量
static const int c_a = 10;
static const int c_b = 11;
cout << "静态常量p_a的地址是:" << (int)&c_a << endl;
cout << "静态常量p_b的地址是:" << (int)&c_b << endl;
cout << "两个静态常量相差:" << (int)&c_a - (int)&c_b << " 个字节" << endl << endl;
//常量
//字符串常量
cout << "字符串常量的地址:" << (int)&"hello word" << endl;
//const修饰的变量
//const 修饰的局部变量 const修饰的全局变量
cout << "全局常量cp_a的地址是:" << (int)&cp_a << endl;
cout << "全局常量cp_b的地址是:" << (int)&cp_b << endl;
cout << "两个全局常量相差:" << (int)&cp_a - (int)&cp_b << " 个字节" << endl << endl;
//const 修饰的局部变量
const int sp_a = 10;
const int sp_b = 11;
cout << "局部常量sp_a的地址是:" << (int)&sp_a << endl;
cout << "局部常量sp_b的地址是:" << (int)&sp_b << endl;
cout << "两个局部常量相差:" << (int)&sp_a - (int)&sp_b << " 个字节" << endl << endl;
system("pause");
return 0;
}
总结:
- c++在程序运行前分为全局区和代码区
- 代码区特点是共享和只读
- 全局区中的存放全局变量、静态变量、常量
- 常量区中存放 const修饰的全局常量 和 字符串常量
1.2、程序运行后
栈区:
由编译器自动分配和释放,存放函数的参数值,局部变量等
注意事项:
不要返回局部变量的地址,栈区开辟的数据由编译器自动释放
eg:
#include <iostream>
using namespace std;
//声明函数
//返回函数内局部变量的地址
int* ftion(int b) {
int a = 90;
return &a;
}
int main()
{
cout << "栈区练习:" << endl << endl;
//栈区存放的是 函数的参数值 和局部变量 、局部常量
//注意不要返回 局部变量的地址 ,因为咱栈区由系统分配和释放 ,函数调用完之后就被释放了,所以返回的地址已经无效了
int* p = ftion(1);;
cout << "*p=" << *p << endl; //系统会保留一次返回的地址
cout << "*p=" << *p << endl; //再次调用就无效了
system("pause");
return 0;
}
堆区:
由程序员分配释放,程序员不释放,程序结束时由操作系统释放回收
在c++中主要利用new在堆区开辟内存
eg:
#include <iostream>
using namespace std;
//声明一个函数 返回一个地址
//利用new关键字 可以将数据开辟到堆区
//函数体内的指针 本质也是局部变量,放在栈区 ,指针保存的是堆区数据的地址
int* func()
{
int* p = new int(10);
return p;
}
int main()
{
cout << "堆区练习:" << endl << endl;
int* ptr = func();
cout << "*ptr=" << *ptr << endl;
cout << "*ptr=" << *ptr << endl;
cout << "ptr=" << ptr << endl; //返回的是堆区的地址
system("pause");
return 0;
}
总结:
堆区数据由程序员管理开辟和释放
堆区数据利用new关键字进行开辟内存
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性