【C++】C++核心编程(一)---内存四区
创始人
2024-05-31 23:20:47

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

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

在这里插入图片描述

内存四区的意义:不同区域存放的数据,赋予不同的生命周期,给我们更灵活的编程创造条件。

1.程序运行前:

在程序编译后,生成了exe可执行程序,未执行该程序前分为2个区域(代码区、全局区)

  1. 代码区
    存放CPU执行的机器指令
    代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可
    代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令
  2. 全局区
    全局变量和静态变量存放在此
    全局区还包含了常量区,字符串常量和其他常量也存放在此
    该区域的数据在程序结束后由操作系统释放
  • 案例演示:
#include 
using namespace std;// 全局区:全局变量、静态变量(static 数据类型 变量名)、常量(字符串常量、全局常量(const修饰的全局变量))
// 不在全局区中的:局部变量、const修饰的局部变量(局部常量)// 全局变量
int global_a = 10;
int global_b = 20;// 全局常量
const int global_const_a = 10;
const int global_const_b = 20;int main() {// 局部变量int local_a = 10;int local_b = 20;cout << "局部变量a的内存地址为:" << (int)&local_a << endl;cout << "局部变量b的内存地址为:" << (int)&local_b << endl;cout << "全局变量a的内存地址为:" << (int)&global_a << endl;cout << "全局变量b的内存地址为:" << (int)&global_b << endl;// 静态变量static int a = 10;static int b = 20;cout << "静态变量a的内存地址为:" << (int)&a << endl;cout << "静态变量b的内存地址为:" << (int)&b << endl;// 常量// 字符串常量cout << "字符串常量的内存地址为:" << (int)&"nining" << endl;// 全局常量cout << "全局常量a的内存地址为:" << (int)&global_const_a << endl;cout << "全局常量b的内存地址为:" << (int)&global_const_b << endl;// 局部常量const int local_const_a = 10;const int local_const_b = 20;cout << "局部常量a的内存地址为:" << (int)&local_const_a << endl;cout << "局部常量b的内存地址为:" << (int)&local_const_b << endl;system("pause");return 0;
}
  • 输出结果:
局部变量a的内存地址为:16776620
局部变量b的内存地址为:16776608
全局变量a的内存地址为:10862592
全局变量b的内存地址为:10862596
静态变量a的内存地址为:10862600
静态变量b的内存地址为:10862604
字符串常量的内存地址为:10853380
全局常量a的内存地址为:10853168
全局常量b的内存地址为:10853172
局部常量a的内存地址为:16776596
局部常量b的内存地址为:16776584
请按任意键继续. . .

我们可以看到全局变量、静态变量、字符串常量、全局常量(存放在全局区)的内存地址都很相近,同时局部变量、局部常量(存放在栈区)的内存地址也很相近,存放在全局区的数据内存地址与存放在栈区的数据内存地址具有较大的差别。

2.程序运行后:

  1. 栈区
    由编译器自动分配释放,存放函数的参数值,局部变量等
    注意:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放
  • 案例演示:
#include 
using namespace std;// 创建一个函数,返回局部变量的地址
int* func(int b) //形参数据也放在栈区
{b = 100;int a = 10; //局部变量 存放在栈区,栈区的数据在函数执行完后自动释放return &a;
}int main() {int* p = func(1);cout << *p << endl; //第一次能够正确的打印,是因为编译器对释放的数据进行了一次保留cout << *p << endl; //第二次出现乱码,也就是不能够正确地打印数据,是因为编译器不再保留数据了system("pause");return 0;
}
  • 输出结果:
10
16584764
请按任意键继续. . .
  1. 堆区
    由程序员分配释放,若程序员不释放,程序结束时由操作系统回收,在C++中主要利用new关键字在堆区开辟内存
    new操作符
    堆区开辟的数据由程序员手动开辟、手动释放,开辟数据利用操作符new
    语法1:数据类型 * p = new 数据类型(初始值)
    利用new创建的数据,会返回该数据对应的类型的指针
    语法2:数据类型 * arr = new 数据类型[数组长度]
    delete操作符
    堆区开辟的数据由程序员手动开辟、手动释放,释放利用操作符delete
    语法1:delete p;
    语法2:delete[] arr;
  • 案例演示:
#include 
using namespace std;/*
new int(10);
delete 变量名; 
nem int[10];
delete [] 变量名;
*/int* func()
{// 利用new关键字可以将数据开辟到堆区// 指针,在此本质上也是局部变量,放在栈上,指针保存的数据是放在了堆区int* p = new int(10);return p;
}void func2()
{// 利用new关键字开辟一个数组到堆区int* arr = new int[10]; // 10代表数组有10个元素for (int i = 0; i < 10; i++){arr[i] = i + 100;}for (int i = 0; i < 10; i++){cout << arr[i] << endl;}// 释放堆区数组// 释放的时候要加上一个中括号delete[] arr;
}int main() {// 在堆区开辟数据int* p = func();cout << *p << endl;cout << *p << endl;// 如果想要释放堆区的数据,利用关键字 deletedelete p;// cout << *p << endl; // 已经将数据释放了,如果再访问将会报错func2();system("pause");return 0;
}
  • 输出结果:
10
10
100
101
102
103
104
105
106
107
108
109
请按任意键继续. . .

相关内容

热门资讯

话剧《最后一间报刊亭》首演,编... (来源:千龙网)一座报刊亭,见证三十载光阴流转;一叠油墨纸张,承载几代人的文化记忆。1月10日,中国...
科技特派团精准赋能南涧红花产业...   2022年,云南省农业科学院牵头实施“百团千员助农增收”行动,组织1300余名科技人员,组成12...
沪滇专家联手书写中老医疗合作温...   日前,昆明市儿童医院临床免疫科联合院内多学科团队,与上海复旦大学附属儿科医院专家线上线下协同作战...
伊朗德黑兰省省长称抗议群体已大... 来源:央视新闻客户端当地时间12日,伊朗德黑兰省省长表示,部分抗议者在9日晚间“选择了自己的路”,但...
拦截高风险交易近300笔 (来源:中国消费者报)  本报杭州讯(记者郑铁峰)记者1月8日获悉,2025年以来,浙江省永康市市场...