C++学习笔记(14)—— 内存分区模型

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

  1. 代码区:存放函数体的二进制代码,由操作系统进行管理
  2. 全局区:存放全局变量和静态变量以及常量
  3. 栈区    :由编译器自动分配释放,存放函数的参数值,局部变量等
  4. 堆区    :由程序员分配和释放,若程序员不释放,程序结束时由操作系统释放回收

 

内存四区的意义:

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

 

1.1、程序运行前

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

  • 代码区:
  1. 存放cpu执行的机器指令
  2. 代码区是共享的,共享的目的是对于频繁操作被执行的程序,只需要在内存中有一份代码即可
  3. 代码区是只读的,使其只读的原因是防止程序意外地修改了他的指令
  • 全局区:
  1. 全局变量和静态变量存放在此
  2. 全局区还包含了常量区(字符串常量和其它常量(const))
  3. 全局区的数据在程序执行结束后由操作系统系释放

 

 

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关键字进行开辟内存

posted @ 2022-04-15 09:18  雾枫  阅读(29)  评论(0编辑  收藏  举报