C++系列第九篇 数据类型下篇 - 复合类型(指针高级应用)
系列文章
C++ 系列 前篇 为什么学习C++ 及学习计划-CSDN博客
C++ 系列 第一篇 开发环境搭建(WSL 方向)-CSDN博客
C++ 系列 第二篇 你真的了解C++吗?本篇带你走进C++的世界-CSDN博客
C++ 系列 第三篇 C++程序的基本结构-CSDN博客
C++ 系列 第四篇 C++ 数据类型上篇—基本类型-CSDN博客
C++ 系列 第五篇 C++ 算术运算符及类型转换-CSDN博客
C++系列第六篇 数据类型下篇 - 复合类型(数组及字符串)-CSDN博客
C++系列第七篇 数据类型下篇 - 复合类型(结构体、共用体及枚举)-CSDN博客
C++系列第八篇 数据类型下篇 - 复合类型(指针及动态内存申请)-CSDN博客
前言
这一章节进行复合类型最后一部分的介绍,主要是指针的一些高级应用,包括指针和数组的的关系,指针和字符串的关系,指针和结构的关系, 变量基于内存位置进行的分类。 还会简单介绍下 C++特有的动态数组,vector 和 array。
指针和数组
进行过C编程的人一定进行过指针和数组等价使用,即申请的是数组,按指针操作,或者一个指针指向一块申请的内存,按数组进行操作。 C++中指针和数组也可以进行等价使用。指针和数组基本等价的原因在于指针算术和C++内部处理数组的方式。
首先,将整数变量加 1 后,其值将增加1:但将指针变量加1 后,增加的量等于它指向的类型的字节数。将指向 double 的指针加1 后,如果系统对 double 使用 8 个字节存储,则数值将增加 8;将指向short 的指针加1 后,如果系统对 short 使用 2 个字节存储,则指针值将增加 2。

如上的示例除了说明指针的数值计算外,还有一个比较重要的点就是将数组名解释为地址。大部分情况两者可以等价操作,可以像示例中一样使用指针的数值计算一样进行数组的数值计算,同时也能像取数组元素一样操作指针。
我们为什么说大部分情况可以等价操作,那就是有不等价的情况,两种情况,一是 指针是一个变量,可以像示例中 ptr = ptr+1; 即可以修改指针的值,而数组名不可以修改,它是常量;二是使用sizeof 进行计算,对数组应用 sizeof 运算符得到的是数组的长度,而对指针应用 sizeof 得到的是指针的长度,即使指针指向的是一个数组。

还有一个平常容易忽略的点是数组的地址 ,对数组取地址时,数组名不会被解释为其地址。我们上边说了数组名被解释为数组的地址,相当于第一个数组元素的地址,当对数组名应用地址运算符时,得到的是整个数组的地址,从数字上说,这两个地址相同;但从概念上说,&ptr[0](即 ptr)是一个4 字节内存块的地址,而&ptr是一个20 字节内存块的地址。因此,表达式ptr+1将地址值加4,而表达式&ptr+1 将地址加 20。换句话说,ptr是一个int 指针,而&ptr是一个这样的指针,即指向包含5个元素的int数组(int(*)[5])。具体使用的时候一定要注意。
指针和字符串
有三个特别需要注意的点
1、在cout 和多数 C++表达式中,char 数组名、char 指针以及用引号括起的字符串常量都被解释为字符串第一个字符的地址。
如果给 cout 提供一个字符的地址,则它将从该字符开始打印,直到遇到空字符为止。这意味着可以将指向char 的指针变量作为cout 的参数,因为它也是char 的地址。

cstring 中的strcpy 具体实现如图,可以看到从第一个字符的地址开始进行处理,直到碰到结束符为止

2、在将字符串读入程序时,应使用已分配的内存地址。该地址可以是数组名,也可以是使用 new初始化过的指针。
字符串读入一定是要有具体内存去存储它的,否则胡乱存储到未知内存的话,就会造成内存访问异常,进而出现程序挂死。而数组本身是一个已经由编译器分配好内存的的变量,new初始化过的指针也指向了一个动态分配好的内存。但是要特别注意,数组或者new 分配的内存要足够大,能够容纳需要读入的字符串,否则会造成内存访问溢出。
3、字符串赋值给字符数组时要使用strcpy 或者 strncpy 等拷贝函数, 直接 "array = ptr" 这种操作是不可取的,因为ptr 是一个指针,其值是一个地址,直接赋值相当于 把ptr 指向的地址 赋值给array 数组了,但是array 数组本身是有一个地址的,编译器不允许修改 数组变量的地址

指针和结构体
可以运行时创建动态结构,“动态”意味着内存是在运行时,而不是编译时分配的。由于类与结构非常相似,结构的大部分技术也适用于类。将new 用于结构由两步组成:创建结构和访问其成员。要创建结构,需要同时使用结构类型和new。例如,要创建一个未命名的 inflatable 类型,并将其地址赋给一个指针,可以这样做:inflatable *ps = new inflatable; 这将把足以存储 inflatable 结构的一块可用内存的地址赋给 ps。
动态创建的结构,不能将成员运算符句点用于结构名,因为这种结构没有名称,只是知道它的地址。需要使用箭头成员运算符(->) 来访问成员,这点和C 语言完全一眼。。例如,如果ps 指向一个inflatable 结构,则 ps->price 是被指向的结构的 price 成员。
另一种访问结构成员的方法是,如果 ps 是指向结构的指针,则*ps 就是被指向的值--结构本身。由于*ps 是一个结构,因此(*ps).price 是该结构的 price 成员。但基本没这么用的,平白增加程序的复杂度。
局部变量、静态变量及动态变量
根据分配内存的方法,或者是变量所属内存位置的不同, C及 C++有 3 种管理数据内存的方式:自动存储、静态存储和动态存储(有时也叫作自由存储空间或堆), 对应的变量分别也叫局部变量、静态变量及动态变量。
在函数内部定义的常规变量使用自动存储空间,被称为自动变量(automatic variable),这意味着它们在所属的函数被调用时自动产生,在该函数结束时消亡。自动变量是一个局部变量,其作用域为包含它的代码块。代码块是被包含在花括号中的一段代码。注意是代码块,而不是函数,我们目前为止举例都是整个函数举例,但其实一个函数里也可以分不同代码块的,如下所示, value 整形变量定义时使用{} 进行了包含, 所以属于一个单独的代码块,在代码快外使用,提示未定义。

静态存储是整个程序执行期间都存在的存储方式。使变量成为静态的方式有两种: 一种是在函数外面定义它;另一种是在声明变量时使用关键字static, 如 static double fee=56.50;。
自动存储和静态存储的关键在于,这些方法严格地限制了变量的寿命。变量可能存在于程序的整个生命周期(静态变量),也可能只是在特定函数被执行时存在(自动变量)。
动态存储new 和delete 运算符提供了一种比自动变量和静态变量更灵活的方法。它们管理了一个内存池,这在 C++中被称为自由存储空间(free store)或堆(heap)。该内存池同用于静态变量和自动变量的内存是分开的。new 和delete 使得一个变量能够在一个函数中分配内存,而在另一个函数中释放它。因此,数据的生命周期不完全受程序或函数的生存时间控制。
与使用常规变量相比,使用 new 和delete 让程序员对程序如何使用内存有更大的控制权。然而,内存管理也更复杂了。在栈中,自动添加和删除机制使得占用的内存总是连续的,但new和delete的相互影响可能导致占用的自由存储区不连续,这使得跟踪新分配内存的位置更困难。
如果使用new 运算符在自由存储空间(或堆)上创建变量后,没有调用 delete,则即使包含指针的内存由于作用域规则和对象生命周期的原因而被释放,在自由存储空间上动态分配的变量或结构也将继续存在。实际上,将会无法访问自由存储空间中的结构,因为指向这些内存的指针无效。这将导致内存泄漏。被泄漏的内存将在程序的整个生命周期内都不可使用;这些内存被分配出去,但无法收回。
我们在上一篇也提到过,指针时危险的,因为它们允许执行对计算机不友好的操作,如使用未经初始化的指针来访问内存或者试图释放同一个内存块两次,或者向上边提到的,因为未进行delete 操作,造成内存泄漏。大家使用的时候一定要特别注意。
数组的替代品
模板类 vector 和array是数组的替代品
模板类 vector 类似于string 类,是一种动态数组。可以在运行阶段设置vector 对象的长度,可在末尾附加新数据,还可在中间插入新数据。基本上,它是使用 new 创建动态数组的替代品。实际上,vector类确实使用 new 和 delete 来管理内存,但这种工作是自动完成的。
要使用vector 对象,必须包含头文件vector。其次,vector 包含在名称空间std 中,因此可使用using 编译指令、using 声明或std::vector。第三,模板使用不同的语法来指出它存储的数据类型。第四,vector 类使用不同的语法来指定元素数。
如下vi 是一个空的vector<int>对象 。 使用时可以使用对应的方法 resize 重新指定需要的大小并 按正常数组方式进行使用。
vd 是一个有三个元素的 vector<double> 对象,定义时分配了空间,所以可以直接访问范围内元素。

vector 类的功能比数组强大,但付出的代价是效率稍低。如果需要的是长度固定的数组,使用数组是更佳的选择,但代价是不那么方便和安全。鉴于此,C++11 新增了模板类array,它也位于名称空间std中。与数组一样,array 对象的长度也是固定的,也使用栈(静态内存分配),而不是自由存储区,因此其效率与数组相同。 好多学习资料上说array 有边界检查,不够准确,不是所有情况下都有边界检查,如下所示,使用max_size方法 ,获取到的确实 是定义时候的大小,但是 可以像C数组一样,超边界赋值,编译器并没有报错。只有通过at() 方法 时 才会捕捉这种越界错误,并进行停止,但是效率会 降低。
到这里为止,符合类型就都总结完了,意味着数据类型也都学完了,下一篇我们将开始表达式和语句的总结学习。
相关文章:
C++系列第九篇 数据类型下篇 - 复合类型(指针高级应用)
系列文章 C 系列 前篇 为什么学习C 及学习计划-CSDN博客 C 系列 第一篇 开发环境搭建(WSL 方向)-CSDN博客 C 系列 第二篇 你真的了解C吗?本篇带你走进C的世界-CSDN博客 C 系列 第三篇 C程序的基本结构-CSDN博客 C 系列 第四篇 C 数据类型…...
python三大开发框架django、 flask 和 fastapi 对比
本文讲述了什么启发了 FastAPI 的诞生,它与其他替代框架的对比,以及从中汲取的经验。 如果不是基于前人的成果,FastAPI 将不会存在。在 FastAPI 之前,前人已经创建了许多工具 。 几年来,我一直在避免创建新框架。首先&…...
html基础2
视频video <video src"视频的路径"controls"控制播放、暂停、音量等"autoplay"自动播放"loop"循环播放"width"视频播放器的宽度"height"视频播放器的高度"> </video>还有做浏览器兼容的方式…...
基于博弈树的开源五子棋AI教程[5 启发式搜索]
文章目录 1 最大化攻击者/最小化防守者排序2 置换表启发3 杀手表启发4 历史表启发历史表以及杀手表的维护初始化追加杀手表项清空杀手表 启发式搜索的姿势千奇百怪,本文只讨论一下几种 //搜索空间 #define Search_Space_MVA 0 //最优价值攻击者[分数最大] #d…...
JavaScript原型,原型链 ? 有什么特点?
一、原型 JavaScript 常被描述为一种基于原型的语言——每个对象拥有一个原型对象 当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个…...
Unity 问题 之 ScrollView ,LayoutGroup,ContentSizeFitter 一起使用时,动态变化时无法及时刷新更新适配界面的问题
Unity 问题 之 ScrollView ,LayoutGroup,ContentSizeFitter 一起使用时,动态变化时无法及时刷新更新适配界面的问题 目录 Unity 问题 之 ScrollView ,LayoutGroup,ContentSizeFitter 一起使用时,动态变化时无法及时刷新更新适配界面的问题 一、简单介绍…...
linux 中 C++的环境搭建以及测试工具的简单介绍
文章目录 makefleCMakegdb调试 与 coredumpValgrind 内存检测gtest 单元测试 makefile 介绍 安装 : sudo apt install make makefile 的规则: 举例说明 包括:目标文件 、 依赖文件 、 生成规则 使用 : make make clean CMake : CMake是一个…...
448. 找到所有数组中消失的数字
找到所有数组中消失的数字 描述 : 给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。 题目 : LeetCode 448. 找到所有数组中消失的数字: 448. 找…...
为何在下雪天它“失宠”了,传统雪地靴居然不适合下雪穿
随着冬至的到来,一年之中最寒冷的“三九天”正式拉开序幕。近期各地纷纷下起了大雪,在这场大雪中雪地靴似乎“失宠”了。在社交媒体上,有网友吐槽“雪地靴根本不能下雪穿”,后面有不少网友纷纷分享了自己在雪地靴上尴尬的经历&…...
第34节: Vue3 调用内联处理程序中的方法
在UniApp中使用Vue3框架时,你可以在模板中直接调用组件内联处理程序中的方法。以下是一个示例: <template> <view> <button click"handleClick">Click me</button> <p>{{ message }}</p> </view&…...
JavaScript--明明白白Promise (Park One)
明明白白Promise (Park One) Promise是一种用于处理异步操作的特殊对象。它代表了一个尚未完成但最终会完成的操作,并可以在操作完成后返回结果或错误。 Promise有三种状态:pending(进行中)、fulfilled(已完成&#…...
el-form与el-upload结合上传带附件的表单数据(后端篇)
1.写在之前 本文采用Spring Boot MinIO MySQLMybatis Plus技术栈,参考ruoyi-vue-pro项目。 前端实现请看本篇文章el-form与el-upload结合上传带附件的表单数据(前端篇)-CSDN博客。 2.需求描述 在OA办公系统中,流程表单申请人…...
postMessage——不同源的网页直接通过localStorage/sessionStorage/Cookies——技能提升
最近遇到一个问题,就是不同源的两个网页之间进行localstorage或者cookie的共享。 上周其实遇到过一次,觉得麻烦就让后端换了种方式处理了,昨天又遇到了同样的问题。 使用场景 比如从网页A通过iframe跳转到网页B,而且这两个网页…...
上市公司-绿色投资者数据集(2000-2022)
上市公司-绿色投资者数据(2000-2022年)是一份涵盖了过去二十多年中国上市公司绿色投资情况的详细数据集。该数据集包括了各上市公司的股票代码、年份、会计年度、股票简称,以及STPT(特殊处理股票的标识),行…...
3 pandas之dataframe
定义 DataFrame是一个二维数据结构,即数据以行和列的方式以表格形式对齐。 DataFrame特点: 存在不同类型的列大小可变带有标签的轴可对列和行进行算数运算 构造函数 pandas.DataFrame( data, index, columns, dtype, copy)参数解释: 序号…...
vue-内网,离线使用百度地图(地图瓦片图下载静态资源展示定位)
前言 最近发现很多小伙伴都在问内网怎么使用百度地图,或者是断网情况下能使用百度地图吗 后面经过一番研究,主要难点是,正常情况下我们是访问公网百度图片,数据,才能使用 内网时访问不了百度地图资源时就会使用不了&…...
OpenFeign 万字教程详解
OpenFeign 万字教程详解 目录 一、概述 1.1.OpenFeign是什么?1.2.OpenFeign能干什么1.3.OpenFeign和Feign的区别1.4.FeignClient 二、OpenFeign使用 2.1.OpenFeign 常规远程调用2.2.OpenFeign 微服务使用步骤2.3.OpenFeign 超时控制2.4.OpenFeign 日志打印2.5.O…...
全自动双轴晶圆划片机:半导体制造的关键利器
随着科技的飞速发展,半导体行业正以前所未有的速度向前迈进。在这个过程中,全自动双轴晶圆划片机作为一种重要的设备,在半导体晶圆、集成电路、QFN、发光二极管、miniLED、太阳能电池、电子基片等材料的划切过程中发挥着举足轻重的作用。 全自…...
Android Studio 安装和使用
前些天,打开了几年前的一个Android Studio app项目,使用安卓虚拟机仿真app崩溃,怀疑是不是中间升级过Android Studio导致异常的,马上脑子一热卸载了,结果上次踩过的坑,一个没少又踩一次,谨以此文…...
【已解决】Java中,判断:集合中是否包含指定元素(模糊匹配)比如权限中的user:list或者是user:*这种判断
背景描述 在工作中,有时候,我们需要对list中是否包含了指定元素进行判断,但是,有时候又需要支持模糊匹配,这个时候怎么办呢? 比如权限,我们知道,权限不仅可以配置完整的路径&#…...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

