news 2026/8/24 5:31:45

C++学习日志——面向过程篇3.11

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++学习日志——面向过程篇3.11

1.内存的四个区域
C语言在程序执行时,其存储空间主要被分为四个区域:
1)代码区;
2)全局区:
3)堆区;
4)栈区;
而C++的存储区域划分和C语言是类似的,但是由于虚函数等作为C的扩展使得C++还要引入其他的区域来存储(如只读常量区、线程局部存储等),核心的存储分布是一样的。

2.代码区
代码区主要存储我们在ide中编辑的代码,并最终转化为01的二进制数由操作系统管理。代码区有两个特性,第一个是只读:

当程序运行后,这里的调控台也叫可执行文件,在该文件中我们无法对已生成的”Hello world“修改。
第二个特性是共享。对于一个未执行完成的程序,其生成的可执行文件(可以同时打开多个可执行文件)中的代码部分是相同的。

2.全局区
全局区主要存放全局变量、静态变量以及常量。我们先来看全局变量:

对于全局变量g_a和g_b,在main函数中输出其地址,观察发现其地址仅差4(十六进制8,9,A,B,C),这与g_a的数据类型int相符,这说明这两个全局变量的存放地址是连续的,这里我们在声明两个局部变量:

很明显局部变量的存储地址与全局变量存储位置相隔很远且不连续存放;而当我们把c更改为静态变量(添加关键字static后),程序运行结构如下:

此时c的地址和g_a与g_b连续且间隔为4,这说明c的存放空间由局部变量位置被修改至了与全局变量一致的全局区中,当我们把d也修改为静态变量时,发现它的存储空间于c连续,按照声明的先后顺序依次存放至全局区内。

对于常量而言,除了使用const修饰变量,还有一种更常见的字符串常量:

这里输出一个随便的字符串常量位置,发现它即使不和之前的全局变量、静态变量连续,但位置也十分相近,和局部变量时的存储空间差距很大但距离全局变量和静态变量的存储空间又十分相近,这说明字符串常量的存储空间也是位于全局区的。
对于局部常量,我们声明一个对应的局部常量e,并输出其地址:

发现和之前的存储空间相隔很远,把c和d修改为局部变量后再次输出:

发现局部常量e的存储空间是和局部变量之间的距离十分接近,这说明e并非存储于全局区。那全局常量又是如何呢?这里声明一个全局常量g_c观察输出结果:

发现其位置更接近存放于全局区的数据,说明全局常量的存放位置也在全局区。

3.栈区
栈作为一种数据结构,有着限制出入、先进后出的原则。实际上C++、C语言中的栈区也是遵循先进后出原则(LIFO)的,但是这里的堆和栈和并非数据结构中的堆和栈。
栈区和堆区的内存都是程序运行过程中申请和释放的,只是:栈区的内存是由操作系统来控制生命周期,而堆区的内存是根据使用者来控制生命周期的。
提起栈,我们联想到昨天学习过的野指针情况的最后一种情况:

这里也说明过,是把一个常量字符串赋值给一个在栈上的字符串变量,且返回的是栈上的局部变量首地址,在函数结束运行时s被销毁,于是char*(返回值)为野指针。那么这里我们不采用指针的返回而是使用C++的引用效果如何呢?

这里看似可以返回出一个正常值,但实际上也是错误的;因为这里代码希望返回的是字符数组的首地址,理论上输出应该是输出全部字符数组,但是这里的输出仅输出了字符数组的第一个元素;且在函数结束运行返回时s[20]就已经被销毁,实际上是没有s的地址的,就更没有对其取地址这个操作(引用传递的先导条件就是指向地址必须有实际意义)。
回到栈区的存储。栈区的存储内容主要有以下几种:
1)局部变量;
2)形式参数;
3)函数返回地址;
4)寄存器上下文(函数调用时);
除此以外,栈区的特点还有存储区域有限。

注意这里,a和b是函数Test的形式参数,而c和d是该函数内声明的局部变量,输出其内存地址发现地址位置类似,说明存储区域相近。

4.堆区
动态内存分配是C语言中很重要的内容,其中涉及了malloc,relloc以及free等函数的使用场景以及数据结构如链表、数组的空间分配等内容。而C++中使用更加便捷的new和delete来为这些数据结构进行动态内存管理;区别在于,C中的malloc等是函数,而new和delete是运算符。
实际上,动态分配内存就是使用者(程序员)自主的相系统申请数据的空间,而这些空间就是堆区的空间。

关于该程序,首先函数get的返回值是一个指向整型数据类型的指针。a是一个在函数内部申请的局部变量,因此a是存储于栈区的;此时通过运算符new为a分配一个整形类型的数据,并复制为v,该数据是存储于堆区的;当函数返回时,虽然栈区的a被释放掉了,但其指向内存仍然存在,因此只需要将该内存的地址赋值给指针p,所以main函数后续部分可以通过解引用输出p所指向内存的值。
除此以外,C++中使用new、delete运算符还可以实现调用类的构造函数来实例化对象:

最常见的就是初始化一个指向该类的对象的指针变量的初始化。
注意这里是如何使用new这个关键字的——new 数据类型(初值),如果这里不设置任何初值,理论上来讲该指针所指向的内容是一个随机值:

除了在声明中直接在数据类型(这里是int)添加括号,在括号内声明初值以外,也可以换行实现赋初值:

值得注意的是,这里不论是换行赋初值还是不赋初值ide都会默认报错,所以最好是在数据类型后直接声明其初值。
记着要随时释放指针并让指针置空:

关于声明一个指向整形元素数组的指针并使用new、delete运算符申请空间如下:

注意函数Getlist中的p存储于栈区,使用new运算符为其在堆区分配一个数组空间,并用指针p指向它,当函数执行完毕后p会自动释放,其地址不会被释放,而是赋值给了main中的p。此时的p也是一个指向元素为整形的数组的指针变量。在结束程序前,一定要对指针进行释放避免野指针,对于数组使用delete运算符的语句时,要在delete和指针名之间添加'[]'。

5.引用
C++中的引用就和C中的指针类似,除了在传参有区别,函数内部也可以代替指针操作:

通过修改b的值来实现对a的值的修改。这里&符号和指针中的*类似,在指针的声明中表示“这是一个指针类型的变量”,而在除声明外使用则是“对指针的解引用”;这里&在声明时表示“引用”,在其余位置表示“取地址”。注意使用引用修改值时的操作,并不像指针一样要“解引用”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 16:47:32

频率战争:客户一年想不起你一次,这生意基本就危险了

《ToB深水区的生存法则》 第三模块:寻找洋流——关于“增长”的破局之道 (9/12) 朋友,又见面了。 上回咱们聊完“生态位”,老张算是彻底认命了。他不再折腾什么几十号人去搞“行业大脑”的平台梦,老老实实地退回到自己的优势阵地,把团队死死扎根在“中小制造企业的供应…

作者头像 李华
网站建设 2026/7/14 16:47:33

探索中颖无刷BLDC方案:解锁电动与园林工具新动力

中颖无刷 BLDC 方案 芯片: Sh79f1611/Sh79f2202A 电压平台: 18V/36V; 状态: 量产阶段; 功能点: ADC方案,堵转失步,转速环电流环,电压电流保护等; 适配&#x…

作者头像 李华
网站建设 2026/7/14 16:47:33

自动化测试中JSONPath 是解析复杂 JSON 响应的核心工具

在接口自动化测试中,JSONPath 是解析复杂 JSON 响应的核心工具 —— 它能像 XPath 定位 XML 节点一样,精准提取 JSON 中的任意字段,解决了传统 dict 取值(如 res_json["data"]["list"][0]["id"])易出错、不灵活的问题。下面从基础概念、核心…

作者头像 李华
网站建设 2026/7/14 16:47:45

三菱FX5U结构化与ST编程:从模板到实践

三菱FX5U结构化和ST编程模板,IEC编程变量英文命名规范中文注释。 整套包含CC-LINK,轴功能块(12轴程序轻松搞定)。 气缸、真空、普通电机、电滚筒电机、配方统计功能块,整个项目程序完整,并已生产验证。 程序…

作者头像 李华
网站建设 2026/7/14 16:47:45

Qwen3-ASR在智能家居中的创新应用:多设备语音控制

Qwen3-ASR在智能家居中的创新应用:多设备语音控制 想象一下,你刚下班回到家,手里拎着购物袋,只需说一句"打开客厅灯、空调调到24度、播放轻音乐",整个家就瞬间变得舒适温馨——这就是Qwen3-ASR带来的智能家居…

作者头像 李华
网站建设 2026/7/14 16:47:35

RVC模型在Keil5嵌入式开发环境中的交叉编译思考

RVC模型在Keil5嵌入式开发环境中的交叉编译思考 最近和几个做嵌入式开发的朋友聊天,他们都在琢磨一件事:现在AI模型这么火,能不能把像RVC(实时语音转换)这样的模型,塞到他们手头的那些ARM Cortex-M系列芯片…

作者头像 李华