2021-11-06 C++程序内存模型-内存四区

2024-06-10 13:58

本文主要是介绍2021-11-06 C++程序内存模型-内存四区,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

全局区,代码区,栈区,堆区

1. 代码区和全局区

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

1.1 代码区

代码区:存放函数体的二进制代码,由操作系统进行管理
存放CPU执行的机器指令。
代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可。
代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令

1.2 全局区

全局区:存放全局变量和静态变量以及常量
全局变量和静态变量存放在此
全局区还包含了常量区,字符串常量和其他常量也存放在此处
该区域的数据在程序结束后由操作系统释放

#include<iostream>
using namespace std;/*全局变量*/
int c = 10;
int d = 10;/*const修饰全局常量*/
const int g = 10;
const int h = 10;int main()
{/*全局区*//*静态变量  在普通变量前加static,属于静态变量*/static int e = 10;static int f = 10;/*创建普通局部变量*/int a = 10;int b = 10;/*const修饰局部常量*/const int s = 10;const int m = 10;/*常量 1.字符串常量 */cout << "字符串常量的地址为:" << (int)&"hello word" << endl;cout << endl;cout << "局部变量a的地址为:" << (int)&a << endl;cout << "局部变量b的地址为:" << (int)&b << endl;cout << endl;cout << "全局变量c的地址为:" << (int)&c << endl;cout << "全局变量d的地址为:" << (int)&d << endl;cout << endl;cout << "静态变量e的地址为:" << (int)&e << endl;cout << "静态变量f的地址为:" << (int)&f << endl;cout << endl;cout << "const修饰的全局常量g的地址为:" << (int)&g << endl;cout << "const修饰的全局常量h的地址为:" << (int)&h << endl;cout << endl;cout << "const修饰的局部常量s的地址为:" << (int)&s << endl;cout << "const修饰的局部常量m的地址为:" << (int)&m << endl;cout << endl;system("pause");return 0;
}

在这里插入图片描述

总结:

C++中在程序运行前分为全局区和代码区
代码区特点是共享和只读
全局区中存放全局变量,静态变量,常量
常量区中存放const修饰的全局常量和字符串常量

2. 栈区和堆区

2.1 栈区

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

#include<iostream>
using namespace std;/*
栈区数据的注意事项--不要返回局部变量地址
栈区的数据由编译器管理开辟和释放
*/
int * fun()
{int a = 10; //局部变量,存放在栈区,栈区的数据在函数执行完后自动释放return &a; //返回局部变量的地址
}int main()
{int * p = fun(); //接收fun函数的返回值cout << * p << endl;  //第一次可以打印正确的数字,因为编译器做了保留cout << * p << endl; //第二次这个数据就不再保留了,此块内存已被释放system("pause");return 0;
}

2.2 堆区

由程序员分配和释放,若程序员不释放,程序结束时由操作系统收回,C++中主要利用new在堆区开辟内存

#include<iostream>
using namespace std;/*
栈区数据的注意事项--不要返回局部变量地址
栈区的数据由编译器管理开辟和释放
*/
int * fun() //形参数据也会放在栈区
{//利用new关键字,可以将数据开辟到堆区//指针本质是局部变量 ,放在栈上。指针保存的数据放在堆区int* p = new int(10);return p;
}int main()
{//在堆区开辟数据int * p = fun(); //接收fun函数的返回值cout << * p << endl;  system("pause");return 0;
}

3. new操作符

C++中利用new操作符在堆区开辟数据,堆区开辟的数据,由程序员受到开辟,手动释放,释放利用操作符delete。
利用new创建的数据,会返回该数据对应的类型的指针。

#include<iostream>
using namespace std;/*new的基本语法*/
int* func()
{/*在堆区创建整形数据new返回的是该数据类型的指针*/int* p = new int(10);return p;
}void text01()
{int* p = func();cout << *p << endl;//堆区数据由程序员管理释放delete p; 
//	cout << *p << endl;   内存已经释放,再次访问就是非法操作,会报错
}void text02()
{/*创建10个整形数据的数组,在堆区*/int* arr = new int[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()
{//text01();text02();system("pause");return 0;
}

总结

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

这篇关于2021-11-06 C++程序内存模型-内存四区的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1048353

相关文章

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java内存分配与JVM参数详解(推荐)

《Java内存分配与JVM参数详解(推荐)》本文详解JVM内存结构与参数调整,涵盖堆分代、元空间、GC选择及优化策略,帮助开发者提升性能、避免内存泄漏,本文给大家介绍Java内存分配与JVM参数详解,... 目录引言JVM内存结构JVM参数概述堆内存分配年轻代与老年代调整堆内存大小调整年轻代与老年代比例元空

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

C++11委托构造函数和继承构造函数的实现

《C++11委托构造函数和继承构造函数的实现》C++引入了委托构造函数和继承构造函数这两个重要的特性,本文主要介绍了C++11委托构造函数和继承构造函数的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录引言一、委托构造函数1.1 委托构造函数的定义与作用1.2 委托构造函数的语法1.3 委托构造函

C++11作用域枚举(Scoped Enums)的实现示例

《C++11作用域枚举(ScopedEnums)的实现示例》枚举类型是一种非常实用的工具,C++11标准引入了作用域枚举,也称为强类型枚举,本文主要介绍了C++11作用域枚举(ScopedEnums... 目录一、引言二、传统枚举类型的局限性2.1 命名空间污染2.2 整型提升问题2.3 类型转换问题三、C

C++链表的虚拟头节点实现细节及注意事项

《C++链表的虚拟头节点实现细节及注意事项》虚拟头节点是链表操作中极为实用的设计技巧,它通过在链表真实头部前添加一个特殊节点,有效简化边界条件处理,:本文主要介绍C++链表的虚拟头节点实现细节及注... 目录C++链表虚拟头节点(Dummy Head)一、虚拟头节点的本质与核心作用1. 定义2. 核心价值二