奶奶都能看懂的 C++ —— vector 与迭代器

迭代器 (iterator),顾名思义就是能够遍历一组对象的东西。

但是在讲解它之前,我们需要先了解迭代的对象是什么。常见的一种,叫做 vector

vector 类型

使用可变有序序列

我们知道,数学里,vector 是向量的意思。但 C++ 里的向量和它不太一样。它的含义是,具有可变元素个数的有序对象序列

之所以这里说的是对象序列,是因为 vector 可以存储任意类型的对象(我们通常称之为,泛型,即广泛的类型)。

#include <vector> //先引入一下
vector<int> v;
vector<string> v2;
vector<double> v3;

看看上面的代码,这下看懂了。先声明 vector,再用尖括号包裹 vector 存储的数据类型。

OK 现在我们有了空的对象序列。是时候向其中存入元素了。

int i = 10;
v.push_back(i);

使用 .push_back(),允许我们向对象序列的末尾加入元素。由于它是可变长度的,所以可以随意加入对象。

有一点需要注意,vector 永远不会存储引用。也就是说,它会创建圆括号中的对象的拷贝(或者移动该对象)。

你应该已经了解过 string 或者 数组 了。与它们类似,我们也可以用下标运算符,来获取其中某个元素的引用(注意下标从 0 开始,且你不能超过已有元素的范围)。比如:

v.push_back(i);
...
v[5] = 10; // 修改第 6 个元素

要想知道一共有多少元素,避免超出,可以用 size()。不过它返回的是 size_type,你可以用 auto 自动判断类型。

auto vsize = v.size(); // 自动判断返回值类型

初始化问题

我们之前都是先创建空的 vector,然后再装入对象。实际上,我们也可以直接初始化 vector

vector<int> v1{1, 2}; // 1,2
vector<int> v2(2); // 0,0
vector<int> v3(2,3); // 3,3

如上,初始化有花括号(列表初始化)和圆括号(值初始化)两种方式。如果是花括号,那么其中的对象列表就会被加入到 vector 中。比如第一行就初始化了一个包含 2 个数字的 vector。

而如果是圆括号,那么分两种情况:

  • 如果只输入一个值,那么它会创建相应大小 vector,然后初始化所有值为对应对象的默认值(对于 int,这是 0)
  • 如果输入两个值,那么会把第二个值复制,并根据第一个值确定元素个数,填充入 vector。比如第三行,2 个 3

注意,初始化只是创建空白 vector 然后存入并非固定了大小。也就是说,你还可以继续使用 push_back() 加入元素,来扩展其大小。

其实还有个特殊情况。如果花括号内的数据,无法用于初始化一个 vector,那么它会自动作为圆括号处理

vector<string> v{2}; // "",""
vector<string> v1{2,"HELLO"}; // "HELLO","HELLO"

第一行创建了含有 2 个初始值的 string 对象的 vector,第二行则创建了含有 2 个 "HELLO" 的 string 对象的 vector。

实际上,如果你不需要快速创建多个相同的元素,你没有任何理由去用初始化。你可以创建空的 vector,然后随意动态添加元素。

还有一点需要注意。可以直接把一个 vector 复制到另一个:

vector<int> v2;
v2 = v1; //OK

迭代器

好了,既然我们已经有了一个对象的集合,让我们进入正题吧。

vector<int> v1 = {1,2,3,4,5};
for(auto it = v1.begin();it!=v1.end();it++){cout<<*it<<endl;
}
// 输出一行一个 v1 中的元素

等等等,上面的代码有些复杂,我们一点点解释,顺便说明什么是迭代器。

第一行,创建了一个含有 5 个元素的 vector

然后用了一个 for 语句——

什么是迭代器?

首先是初始化:

auto it = v1.begin();

这就是我们的主角,迭代器。我们用了自动类型判断,实际上 it 的类型是:vector<int>::iterator,也就是说,vector 有一个迭代器,而 vector 其中存储的对象是 int 类型的。

嗯,你应该能推测出来,v1.begin() 返回的是一个迭代器类型。顾名思义,它返回的是指向第一个对象的迭代器

你或许注意到了指向这个词,我们在指针那里曾经提到过。比较相似,迭代器也是“一次指向一个对象”,只不过该对象必须存在于一个 vector 中

什么意思呢?你可以理解为,迭代器是和一组对象结合使用的“指针”,在一个时刻,指向其中的一个对象。比如上面那行,就创建了指向第一个对象 1 的迭代器。

那么这样有什么好处呢?我们先来看 for 的第三部分。

it++;

居然对一个迭代器用了自增运算符!这就是迭代器和指针的区别了——由于它指向一组对象,所以可以随意调整,让它指向其它对象,只要目标对象存在于组内。

我们之前提到,vector 是有序的,所以才能使用下标运算符。而正是这种有序性,使自增自减成为可能。

如果增加迭代器,就是让它指向当前对象之后的元素;如果减少迭代器,就是让它指向当前对象之前的元素。

看看下面的例子:

vector<int> v = {233,234,114,432,534};
auto it = v.begin(); // index = 0,*it = 233
it++; // index = 1,*it = 234
it += 2; //index = 3,*it = 432
it -= 3; //index = 0,*it = 233

index 表示当前指向对象的下标。*it 表示指向对象的值。

先不用管那个星号,我们下面会涉及。

好的,第二部分:

it != v1.end();

条件判断,用的是不等号。v1.end() 返回的是指向 vector 列表最后一个元素下一地址的迭代器。(之所以不使用比较符号,是因为并不是所有迭代器都可以比较,但是它们都支持不等号/等号,使用不等号更加通用。)

也就是说,它并不指向任何元素,但是如果你有一个指向最后一个元素的迭代器,那么再加一,就指向该位置。

回忆一下 for 的使用方法。当这个不等号条件不满足时,大括号内的语句不会被执行。即,当完成最后一个元素的处理后(在这个例子里,输出了 5 这个数),条件判断为假,循环结束。

综上,上面代码的输出是:

1
2
3
4
5

也就是说,这样编写代码,允许我们遍历序列中的所有元素,而不会漏掉最后一个。

注意,任何使用迭代器的场景,都不能涉及更改序列大小,否则迭代器会失效。(这是因为,vector 大小是动态扩展的,更改大小可能会自动移动位置来保证充足内存空间,导致迭代器指向的序列失效)

算术运算

实际上,我们可以计算指向同一序列的两个迭代器的差值

vector<int> v(10);
auto it = v.begin();
auto it2 = v.end();
cout<<it2-it<<endl; // output: 10

输出结果是 10。可视化一下,实际上是这样的(数字表示下标):

iterator

解引用

你或许注意到了,我们在上面的代码和注释里里用了同样在指针那一节介绍的 * 解引用符。

这是因为,迭代器也和指针一样,指向一个位置,用解引用符可以获取位置对应的对象

但是等等。如果你好奇心比较旺盛,可能会尝试这个:

cout<<it<<endl; // Error
cout<<*it<<endl;

你看,我不解引用,不就能看看迭代器指向对象的地址了吗?

然而现实是,这个第一行无法通过编译。

为什么?因为迭代器不是指针,而是一个其它的类型。它只是和指针很像罢了。你可以认为它指向一个地址,从而可以使用解引用运算符,但是你不能把它直接当作指针来用。

当然,既然解引用得到的是一个对象,那么当然可以做许多事情:比如调用函数。

但是要小心,注意优先级,你应该先解引用,再调用函数:

vector<string> v{"Hello","World"};
auto it = v.begin();
cout << (*it).substr(2) << endl; // output: llo
cout << *it.substr(2) << endl; // Error

范围 for 语句

上面我们用三个元素的 for 语句,进行了遍历的操作,其实我们可以简化。

vector<int> v{1,2,3,4};
for(auto i:v){cout<<i<<endl;
}

这个语句叫做,范围 for 语句。它会一个一个取出序列中的元素。

和迭代器不同,它返回对象并拷贝赋值给冒号前的变量(这里是 i),而非其本身。即,修改 i 时,不会修改 v 序列中的任何内容。

如果你想修改,可以把变量创建为引用:

vector<int> v{1,2,3,4};
for(auto &i:v){i = 3;
}
for(auto i:v){cout<<i<<endl;
}
// 3 3 3 3

如果你不想改,但不想拷贝防止性能损耗,可以创建常量引用。

for(const auto &i:v){cout<<i<<endl;// 禁止修改。
}

不止 vector

我们一直在探讨 vector,但实际上,迭代器对于其它的序列也能使用,比如 string。你可以在使用的时候,去查一下是否实现了迭代器。写法都一样,这里省略。

那么范围 for 呢?实际上,实现了 beginend 的类型,都是可以使用的,满足以下条件即可:

  • begin,end 返回的是一个迭代器
  • 迭代器可以自增

也就是说,范围 for 只是一种缩写,只要能用迭代器,就能用。在遍历时推荐使用,可以使代码更易读。

好了,这就是 vector 和迭代器的全部内容,我们下次再继续拆解 C++,奶奶级。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/946025.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI|AI优化公司智能GEO优化解决方案

AI优化企业:智能搜索时代的流量密码与行业标杆 解码AI优化企业排名,揭秘技术驱动的数字增长新范式 AI优化企业如何重构搜索生态?从技术到商业的全链路实践 在生成式AI重塑信息生态的2025年,企业流量获取已从传统SE…

2025年10月深圳离婚律师推荐榜:五强对比与选择指南

正在办理或准备办理离婚手续的深圳居民,普遍面临“找谁更靠谱”的焦虑:财产种类复杂、抚养权争议大、证据链薄弱、对方隐匿资产、涉外因素叠加,任何一环出错都可能让权益缩水。深圳市司法局2024年公开数据显示,全市…

2025年10月杭州丝绸购买榜:万事利湖滨步行街店权威排行

“我想挑一块真正代表杭州韵味的丝绸,送国外导师做纪念,可景区周边小店真假难辨,怕买到混纺。”——这是过去一个月里,我在湖滨步行街被游客反复问到的同一句话。杭州丝绸年零售额已突破180亿元,但“真丝含量”“…

2025年10月加拿大海参产品推荐榜:谷得斯特领衔五强对比

把“加拿大海参”四个字敲进搜索框的人,往往带着同一串疑问:野生和养殖到底差多少?淡干工艺有没有掺糖加盐?价格动辄上千,怎样才不花冤枉钱?2025年进口水产关税维持零税率,但运输、仓储成本上涨,终端零售价普遍…

2025 年花岗岩厂家最新推荐榜:覆盖路沿石、火烧板等全品类,结合行业协会测评数据精选优质厂家

引言 随着花岗岩在市政工程、园林景观、建筑装饰等领域的应用愈发广泛,市场对优质花岗岩产品的需求持续攀升,但市场品牌杂乱、产品质量良莠不齐的问题仍未得到根本解决。据中国石材协会 2024 年度行业测评数据显示,…

2025年10月房产继承律师推荐榜:五强对比与选择指南

继承房产往往伴随家庭情感、资产规模、法律程序三重压力,用户常见场景包括:父母离世后多套房产如何过户、遗嘱真伪遭质疑、继承人身份争议、远郊宅基地与市区商品房混合继承、涉外继承人身份认定等。2025年《民法典继…

https 协议安全算法是在什么时候在客户端和服务器之间确定的

1: 通过wireshark截图看到在TCP 握手之后会通过TLS确认双发的加密算法,TLSv1.2 Application Data • 这说明 TLS 握手已经完成,双方已经协商好密钥,正在用对称加密传输 HTTP 数据。 • 所以在这个阶段,Wireshark …

安卓片段管理即时操作指南-全-

安卓片段管理即时操作指南(全)原文:zh.annas-archive.org/md5/1C597F377D586ADD38C62EB9B81378BB 译者:飞龙 协议:CC BY-NC-SA 4.0前言 智能手机现在已经进入了我们的生活,作为用户和消费者,也作为我们自己的内…

2025 年最新推荐五莲花花岗岩优质厂家榜单:顶尖厂家综合实力测评与选购指南

引言 随着市政工程、园林景观等领域对花岗岩需求的持续增长,五莲花花岗岩市场热度攀升,但产品质量与服务水平的差异给采购方带来诸多困扰。据中国石材协会 2025 年第一季度行业测评数据显示,当前市场上仅 38% 的五莲…

安卓设计模式最佳实践-全-

安卓设计模式最佳实践(全)原文:zh.annas-archive.org/md5/CCA23E4331AE2938F4F732DE02106746 译者:飞龙 协议:CC BY-NC-SA 4.0前言 《Eclipse 下的 Android 开发工具》将向你展示如何使用 Eclipse 的 ADT(Androi…

安卓画布学习手册-全-

安卓画布学习手册(全)原文:zh.annas-archive.org/md5/6E7DDFC03078C433747871B677C39D41 译者:飞龙 协议:CC BY-NC-SA 4.0前言 Android Canvas 学习 提供了 Android Canvas 图形和编程的基本知识和理解。目标读者…

2025 年控制柜生产厂家最新推荐排行榜:聚焦换热机组 / 污水处理等领域品牌技术实力与服务能力测评

引言 在工业自动化深度渗透各行业的当下,控制柜作为设备运行的 “神经中枢”,其性能直接关乎企业生产效率、安全保障与节能成效。当前市场中,控制柜产品涵盖换热机组、污水处理 PLC、变频供水等多个细分领域,然而厂…

VS-和-CrystalReport-报告指南-全-

VS 和 CrystalReport 报告指南(全)原文:zh.annas-archive.org/md5/ecf79c1d847d07af59dd9dbc4960aadd 译者:飞龙 协议:CC BY-NC-SA 4.0前言 对于希望创建成功软件的开发者来说,报告至关重要。Crystal Reports 是…

WebSocket-基础知识-全-

WebSocket 基础知识(全)原文:zh.annas-archive.org/md5/B169597DE295933B6F244191B5501868 译者:飞龙 协议:CC BY-NC-SA 4.0前言 HTML 是 Web 开发中最重要的部分,但在某些方面存在不足,但现在开发人员因其增强…

Paper: Accelerating Vision Transformers with Adaptive Patch Sizes

作者机构:Rohan Choudhury, et al. Carnegie Mellon University, KAIST, General Robotics 论文地址:[https://arxiv.org/pdf/2510.18091v1](https://arxiv.org/pdf/2510.18091v1) 项目地址:Accelerating Vision Tr…

古代的时辰,几更天与现在的时间对应关系是什么?

中国古代的计时系统分为“时辰”和“更(又称鼓)”、“点”,它们与现代24小时制有明确的对应关系。 一、时辰 (12时辰制) 古人将一天分为十二个时辰,每个时辰相当于现在的2个小时。这套系统主要以地支命名。时辰名称…

2025年实用金属铝合金打包机厂家推荐榜单:多场景适配的优质之选

在物流、制造、环保等领域的包装与物料处理环节中,打包机的性能直接影响生产效率与成本控制。为帮助企业精准筛选适配设备,结合产品适配性、技术实力、用户口碑及服务能力等多维度评估,梳理出优质打包机厂家,供不同…

Unity-物理学习指南-全-

Unity 物理学习指南(全)原文:zh.annas-archive.org/md5/3633973ae894fee6b323bd729ac7fc4c 译者:飞龙 协议:CC BY-NC-SA 4.0前言 为了理解在游戏和应用中成功实现 Unity3D 物理组件的含义,开发者必须更好地理解物…

2025年高压加速老化试验箱厂家推荐排行榜,HAAS试验箱,环境应力筛选,可靠性测试设备公司精选

2025年高压加速老化试验箱厂家推荐排行榜,HAAS试验箱,环境应力筛选,可靠性测试设备公司精选 高压加速老化试验箱作为环境应力筛选和可靠性测试的核心设备,在电子、汽车、航空航天等领域发挥着至关重要的作用。随着…

2025年工业风扇厂家权威推荐榜单:覆盖大型工业风扇、车间降温风扇、防爆工业风扇的最新选购指南

2025年工业风扇厂家权威推荐榜单:覆盖大型工业风扇、车间降温风扇、防爆工业风扇的最新选购指南 随着工业4.0时代的深入推进,工业风扇作为工业生产环境中的重要设备,其技术标准和性能要求也在不断提升。在现代化工厂…