C++ Primer 多维数组
专栏简介:本专栏主要面向C++初学者,解释C++的一些基本概念和基础语言特性,涉及C++标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级程序设计技术。希望对读者有帮助!


目录
- 3.6多维数组
- 多维数组的初始化
- 多维数组的下标引用
- 使用范围for语句处理多维数组
- 指针和多维数组
3.6多维数组
严格来说,C++语言没有多维数组,通常所说的多维数组其实是数组的数组。谨记这一点,对今后理解和使用多维数组大有益处。
当一个数组的元素仍然是数组时,通常使用两个维度来定义它:一个维度表示数组本身大小,另外一个维度表示其元素(也是数组)大小:
int ia[3][4];//大小为3的数组,每个元素是含有4个整数的数组
//大小为10的数组,它的每个元素都是大小为20的数组,
//这些数组的元素是含有30个整数的数组
int arr[10][20][30]={0};//将所有元素初始化为0
按照由内而外的顺序阅读此类定义有助于更好地理解其真实含义。在第一条语句中,我们定义的名字是ia,显然ia是一个含有3个元素的数组。接着观察右边发现,ia的元素也有自己的维度,所以ia的元素本身又都是含有4个元素的数组。再观察左边知道,真正存储的元素是整数。因此最后可以明确第一条语句的含义:它定义了一个大小为3的数组,该数组的每个元素都是含有4个整数的数组。
使用同样的方式理解arr的定义。首先arr是一个大小为10的数组,它的每个元素都是大小为20的数组,这些数组的元素又都是含有30个整数的数组。实际上,定义数组时对下标运算符的数量并没有限制,因此只要慈意就可以定义这样一个数组:它的元素还是数组,下一级数组的元素还是数组,再下一级数组的元素还是数组,以此类推。
对于二维数组来说,常把第一个维度称作行,第二个维度称作列。
多维数组的初始化
允许使用花括号括起来的一组值初始化多维数组,这点和普通的数组一样。下面的初始化形式中,多维数组的每一行分别用花括号括了起来:
int ia[3][4] = { // 三个数组,每个元素都是大小为4的数组
{0,1,2,3}, // 第一行的初始值
{4,5,6,7}, // 第二行的初始值
{8,9,10,11} // 第三行的初始值
}
其中内层套着的花括号并非必需的,例如下面的初始化语句,形式上更为简洁,完成的功能和上面这段代码完全一样:
//没有标识每行的花括号,与之前的初始化语句是等价的
int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
类似于一维数组,在初始化多维数组时也并非所有元素的值都必须包含在初始化列表之内。如果仅仅想初始化每一行的第一个元素,通过如下的语句即可:
//显式地初始化每行的首元素
int ta[3][4] = {{0},{4},{8}};
其他未列出的元素执行默认值初始化,这个过程和一维数组一样。在这种情况下如果再省略掉内层的花括号,结果就大不一样了。下面的代码
//显式地初始化第1行,其他元素执行值初始化
int ix[3][4]={0,3,6,9};
含义发生了变化,它初始化的是第一行的4个元素,其他元素被初始化为0。
多维数组的下标引用
可以使用下标运算符来访问多维数组的元素,此时数组的每个维度对应一个下标运算符。
如果表达式含有的下标运算符数量和数组的维度一样多,该表达式的结果将是给定类型的元素;反之,如果表达式含有的下标运算符数量比数组的维度小,则表达式的结果将是给定索引处的一个内层数组:
//用arr的首元素为ia最后一行的最后一个元素赋值
ia[2][3]=arr[0][0][0];
int(&row)[4]=ia[1];//把row绑定到ia的第二个4元素数组上
在第一个例子中,对于用到的两个数组来说,表达式提供的下标运算符数量都和它们各自的维度相同。在等号左侧,ia[2]得到数组ia的最后一行,此时返回的是表示ia最后一行的那个一维数组而非任何实际元素;对这个一维数组再取下标,得到编号为[31的元素,也就是这一行的最后一个元素。
类似的,等号右侧的运算对象包含3个维度。首先通过索引0得到最外层的数组,它是一个大小为20的(多维)数组;接着获取这20个元素数组的第一个元素,得到一个大小为30的一维数组;最后再取出其中的第一个元素。
在第二个例子中,把row定义成一个含有4个整数的数组的引用,然后将其绑定到ia的第2行。
再举一个例子,程序中经常会用到两层嵌套的for循环来处理多维数组的元素:
constexpr size_t rowCnt=3,colCnt二4;
intia[rowCnt][colCnt];//12个未初始化的元素
//对于每一行
for(size_t i = 0;i!=rowCnt;++i) {//对于行内的每一列for(stze_t j=0;j!=colCnt;++j) {//将元素的位置索引作为它的值ia[i][j]= i *colCnt + j;}
}
外层的for循环遍历ia的所有元素,注意这里的元素是一维数组;内层的for循环则遍历那些一维数组的整数元素。此例中,我们将元素的值设为该元素在整个数组中的序号。
使用范围for语句处理多维数组
由于在C++11新标准中新增了范围for语句,所以前一个程序可以简化为如下形式:
size_t cnt = 0;for(auto& row:ia) //对于外层数组的每一个元素for(auto&col:row){//对于内层数组的每一个元素col=cnt;//将下一个值赋给该元素++cnt;//将cnt加1
}
这个循环赋给ia元素的值和之前那个循环是完全相同的,区别之处是通过使用范围for语句把管理数组索引的任务交给了系统来完成。因为要改变元素的值,所以得把控制变量row和col声明成引用类型。第一个for循环遍历ia的所有元素,这些元素是大小为4的数组,因此row的类型就应该是含有4个整数的数组的引用。第二个for循环遍历那些4元素数组中的某一个,因此col的类型是整数的引用。每次迭代把cnt的值赋给ia的当前元素,然后将cnt加1。
在上面的例子中,因为要改变数组元素的值,所以我们选用引用类型作为循环控制变量,但其实还有一个深层次的原因促使我们这么做。举一个例子,考虑如下的循环:
for(const auto&row:ia) // 对于外层数组的每一个元素for(auto col:row) // 对于内层数组的每一个元素cout<<col<<endl;
这个循环中并没有任何写操作,可是我们还是将外层循环的控制变量声明成了引用类型,这是为了避免数组被自动转成指针。假设不用引用类型,则循环如下述形式:
for(auto row : ia)for(auto col:row)
程序将无法通过编译。这是因为,像之前一样第一个循环遍历ia的所有元素,注意这些元素实际上是大小为4的数组。因为row不是引用类型,所以编译器初始化col时会自动将这些数组形式的元素(和其他类垣的数组一样)转换成指向该数组内首元素的指针。这样得到的row的类型就是int*,显然内层的循环就不合法了,编译器将试图在一个int*内遍历,这显然和程序的初衷相去甚远。
要使用范围for语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型。
指针和多维数组
当程序使用多维数组的名字时,也会自动将其转换成指向数组首元素的指针。
定义指向多维数组的指针时,千万别忘了这个多维数组实际上是数组的数组。
因为多维数组实际上是数组的数组,所以由多维数组名转换得来的指针实际上是指向第一个内层数组的指针:
int ia[3][4];//大小为3的数组,每个元素是含有4个整数的数组
int(*p)[4]=ia;//p指向吴有4个整数的数组
p=&ia[2];//p指向ia的尾元素
我们首先明确(*p)意味着p是一个指针。接着观察右边发现,指针p所指的是一个维度为4的数组;再观察左边知道,数组中的元素是整
数。因此,p就是指向含有4个整数的数组的指针。
在上述声明中,括号必不可少:
int*ip[4]//整型指针的数组
int(*ip)[4];//指向舍有4个整数的数组
随着C++11新标准的提出,通过使用auto或者decltype就能尽可能地避免在数组前面加上一个指针类型了:
//输出a中每个元素的值,每个内层数组各占一行
//p指向含有4个整数的数组
for(auto p=ia;p!=ia+3;++p)
//q指向4个整数数组的首元素,也就是说,q指向一个整数
for(auto q=*p;q!=*p+4;++q)
cout<< *q << ' ';
cout<<endl;
外层的for循环首先声明一个指针p并令其指向ia的第一个内层数组,然后依次迭代直到ia的全部3行都处理完为止。其中递增运算++p负责将指针p移动到ia的下一行。
内层的for循环负责输出内层数组所包含的值。它首先后指针q指向p当前所在行的第一个元素。*p是一个含有4个整数的数组,像往常一样,数组名被自动地转换成指
向该数组首元素的指针。内层for循环不断迭代直到我们处理完了当前内层数组的所有元素为止。为了获取内层for循环的终止条件,再一次解引用p得到指向内层数组首元素的指针,给它加上4就得到了终止条件。
当然,使用标准库函数begin和end也能实现同样的功能,而且看起来更简洁一些:
//p指向ia的第一个数组
for(auto p=begin(ia);p!=end(ia);++p){
//q指向内层数组的首元素
for(auto q=begin(*p);q!=end(*p);++q)
cout<<*q<<' ';//输出q所指的整数值
cout<<endl;
在这一版本的程序中,循环终止条件由end函数负责判断。虽然我们也能推断出p的类型是指向含有4个整数的数组的指针,a的类型是指向整数的指针,但是使用auto关键字我们就不必再烦心这些类型到底是什么了。
类型别名简化多维数组的指针
读、写和理解一个指向多维数组的指针是一个让人不胜其烦的工作,使用类型别名能让这项工作变得简单一点儿,例如:
using int_array=int[4];//新标准下类型别名的声明
typedef int int_array[4];//等价的typedef声明
//输出ia中每个元素的值,每个内层数组各占一行
for(int_array * p=ia;p!=ia+3;++p){for(int*q=p;q!=*p+4;++q)cout<<*q<< ' ';cout<<endl;
}程序将类型“4个整数组成的数组“和名为int_array,用类型名int_array定义外层循环的控制变量让程序显得简洁明了。相关文章:
C++ Primer 多维数组
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...
maven mysql jdk nvm node npm 环境安装
安装JDK 1.8 11 环境 maven环境安装 打开网站 下载 下载zip格式 解压 自己创建一个maven库 以后在idea 使用maven时候重新设置一下 这三个地方分别设置 这时候maven才算设置好 nvm 管理 npm nodejs nvm下载 安装 Releases coreybutler/nvm-windows GitHub 一键安装且若有…...
SQL Server中RANK()函数:处理并列排名与自然跳号
RANK()是SQL Server的窗口函数,为结果集中的行生成排名。当出现相同值时,后续排名会跳过被占用的名次,形成自然间隔。与DENSE_RANK()的关键区别在于是否允许排名值连续。 语法: RANK() OVER ([PARTITION BY 分组列]ORDER BY 排序…...
如何运行Composer安装PHP包 安装JWT库
1. 使用Composer Composer是PHP的依赖管理工具,它允许你轻松地安装和管理PHP包。对于JWT,你可以使用firebase/php-jwt这个库,这是由Firebase提供的官方库。 安装Composer(如果你还没有安装的话): 访问Co…...
最新功能发布!AllData数据中台核心菜单汇总
🔥🔥 AllData大数据产品是可定义数据中台,以数据平台为底座,以数据中台为桥梁,以机器学习平台为中层框架,以大模型应用为上游产品,提供全链路数字化解决方案。 ✨奥零数据科技官网:http://www.aolingdata.com ✨AllData开源项目:https://github.com/alldatacenter/…...
【OS】AUTOSAR架构下的Interrupt详解(上篇)
目录 前言 正文 1.中断概念分析 1.1 中断处理API 1.2 中断级别 1.3 中断向量表 1.4 二类中断的嵌套 1.4.1概述 1.4.2激活 1.5一类中断 1.5.1一类中断的实现 1.5.2一类中断的嵌套 1.5.3在StartOS之前的1类ISR 1.5.4使用1类中断时的注意事项 1.6中断源的初始化 1.…...
大数据挖掘--两个角度理解相似度计算理论
文章目录 0 相似度计算可以转换成什么问题1 集合相似度的应用1.1 集合相似度1.1文档相似度1.2 协同过滤用户-用户协同过滤物品-物品协同过滤 1.2 文档的shingling--将文档表示成集合1.2.1 k-shingling1.2.2 基于停用词的 shingling 1.3 最小哈希签名1.4 局部敏感哈希算法&#…...
Win10微软商店重新安装指南
Win10微软商店重新安装指南 在使用Windows 10操作系统的过程中,微软商店(Microsoft Store)作为官方提供的应用下载平台,一直是用户获取和安装各类应用程序的重要渠道。然而,有时用户可能会遇到微软商店无法找到或误删的情况,这无疑给软件的安装和管理带来了不便。本文将…...
操作系统和中间件的信息收集
在浏览器中收集操作系统与中间件信息时,主要通过客户端JavaScript(用于操作系统/浏览器信息)和服务器端脚本(用于中间件信息)实现。以下是分步指南: 一、客户端操作系统信息收集(JavaScript&am…...
项目集成Spring Security授权部分
一、需求分析 业务背景 当前项目采用前后端分离架构,后端需要对接口访问进行严格控制,防止未授权访问。鉴于系统需要支持高并发与分布式部署,采用无状态认证方式显得尤为重要。 核心需求 无状态认证:使用 JWT 作为令牌࿰…...
5. k8s二进制集群之ETCD集群部署
下载etcd安装包创建etcd配置文件准备证书文件和etcd存储目录ETCD证书文件安装(分别对应指定节点)创建证书服务的配置文件启动etcd集群验证etcd集群状态继续上一篇文章《k8s二进制集群之ETCD集群证书生成》下面介绍一下etcd证书生成配置。 下载etcd安装包 https://github.com…...
MV结构下设置Qt表格的代理
目录 预备知识 模型 关联 刷新 示例 代理 模型 界面 结果 完整资料见: 所谓MV结构,是“model-view”(模型-视图)的简称。也就是说,表格的数据保存在model中,而视图由view实现。在我前面的很多博客…...
二维数组 C++ 蓝桥杯
1.稀疏矩阵 #include<iostream> using namespace std;const int N 1e4 10; int a[N][N];int main() {int n, m; cin >> n >> m;for (int i 1; i < n; i) {for (int j 1; j < m; j) {cin >> a[i][j];}}for (int j m; j > 1; j--) {for (i…...
【Linux】文件描述符
初识文件 之前我们认识到当我们进行创建出一个空文件在磁盘上也是占用一部分空间的,因为文件的组成是由文件内容和文件属性共同构成。 文件内容属性,那我们对文件进行操作无外乎就是对内容和属性两个方面进行操作。 文件在磁盘上进行存储,…...
大语言模型的个性化综述 ——《Personalization of Large Language Models: A Survey》
摘要: 本文深入解读了论文“Personalization of Large Language Models: A Survey”,对大语言模型(LLMs)的个性化领域进行了全面剖析。通过详细阐述个性化的基础概念、分类体系、技术方法、评估指标以及应用实践,揭示了…...
AI 编程工具—Cursor进阶使用 Agent模式
AI 编程工具—Cursor进阶使用 Agent模式 我们在使用Cursor 的是有,在Composer 模式下,提交的是有两种模式 Normal 模式,也就是默认的模式Agent 模式Agent 模式可以帮我们生成代码文件,执行程序,安装依赖,并且完成一些列的工作 这里有个点很重要就是在Agent 模式下,Cur…...
【AI大模型】DeepSeek API大模型接口实现
目录 一、DeepSeek发展历程 2023 年:创立与核心技术突破 2024 年:开源生态与行业落地 2025 年:多模态与全球化布局 性能对齐 OpenAI-o1 正式版 二、API接口调用 1.DeepSeek-V3模型调用 2.DeepSeek-R1模型调用 三、本地化部署接口调…...
Qt展厅播放器/多媒体播放器/中控播放器/帧同步播放器/硬解播放器/监控播放器
一、前言说明 音视频开发除了应用在安防监控、视频网站、各种流媒体app开发之外,还有一个小众的市场,那就是多媒体展厅场景,这个场景目前处于垄断地位的软件是HirenderS3,做的非常早而且非常全面,都是通用的需求&…...
Kafka分区策略实现
引言 Kafka 的分区策略决定了生产者发送的消息会被分配到哪个分区中,合理的分区策略有助于实现负载均衡、提高消息处理效率以及满足特定的业务需求。 轮询策略(默认) 轮询策略是 Kafka 默认的分区策略(当消息没有指定键时&…...
【归属地】批量号码归属地查询按城市高速的分流,基于WPF的解决方案
在现代商业活动中,企业为了提高营销效果和资源利用效率,需要针对不同地区的市场特点开展精准营销。通过批量号码归属地查询并按城市分流,可以为企业的营销决策提供有力支持。 短信营销:一家连锁餐饮企业计划开展促销活动…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
