news 2026/4/19 3:46:19

C++零基础到工程实战(4.3.3):vector数组访问与遍历

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++零基础到工程实战(4.3.3):vector数组访问与遍历

目录

一、前言

二、vector是什么

2.1 vector本质上是“可变长数组”

2.2 vector和普通数组的区别

(1)普通数组的特点:

(2)vector 的特点:

2.3 vector为什么适合工程开发

2.4 vector内部空间默认是什么状态

三、vector的定义与初始化

3.1 vector使用的是模板类型

3.2 vector的几种初始化方式

(1)空vector

(2)指定初始大小

(3)列表初始化

四、vector增加、修改与大小获取

4.1 push_back:在尾部追加元素

4.2 size:获取当前元素个数

4.3 下标访问和修改元素

4.4 使用下标访问时要注意什么

五、vector的三种遍历方式

5.1 下标遍历

(1)执行过程

(2)这种方式的优点

(3)这种方式的缺点

5.2 迭代器遍历

(1)iterator是什么

(2)这一句要怎么拆开理解

1)std::vector ::iterator

2)itr

3)datas.begin()

(3)begin 和 end 分别是什么

1)begin():

2)end():

(4)为什么要写 *itr

(5)itr++是什么意思

(6)为什么说vector迭代器很像指针

5.3 C++11范围for遍历

(1)这句代码怎么理解

(2)这里的d到底是什么

(3)&引用是什么意思

(4)auto& d为什么常用

(5)如果不想修改元素怎么办

六、本节代码完整示例

七、重要知识点

7.1 vector的核心特点

7.2 本节必须掌握的几个操作

7.3 初学者最容易犯错的地方

(1)空 vector 直接用下标赋值

(2)把 end() 理解成最后一个元素

(3)把迭代器当成元素值

(4)不理解 auto& d 中的 &


一、前言

在前面的内容中,我们已经学习了普通数组,知道数组本质上是一块连续的内存空间,可以通过下标快速访问元素

但是普通数组有一个明显特点:

长度一旦确定,后续就很难灵活改变。

比如:

int arr[5];

这里数组大小就是 5,后面不能自动变成 10、20 或更多。

而在实际开发中,我们经常会遇到一种场景:

一开始并不知道到底要存多少个数据,只有在程序运行过程中,数据才会不断加入

这时候,普通数组就不够方便了,于是 C++ 标准库给我们提供了一个非常常用的容器:

vector

vector可以理解为:

一个长度可以动态变化的数组容器。

它既保留了数组“连续空间、访问速度快”的特点,又提供了更灵活的操作方式。因此,在工程开发中,vector的使用频率非常高。

本节我们先不去讲查找、删除、插入和排序,而是专门把最基础也是最重要的内容讲清楚:

  • vector是什么
  • vector如何定义和初始化
  • vector如何访问和修改元素
  • vector如何遍历
  • 什么是迭代器
  • begin()end()是什么意思
  • for (auto& d : datas)里的d&到底是什么

二、vector是什么

2.1 vector本质上是“可变长数组”

vector是 C++ 标准库中的一个 STL 容器,头文件是:

#include <vector>

它本质上可以看成一个动态数组

普通数组例如:

int arr[5];

长度在定义时就固定了,后面不能自动变大。

vector不一样,例如:

vector<int> datas;

这里虽然现在没有元素,但后面可以不断:

datas.push_back(10); datas.push_back(20); datas.push_back(30);

这样数组大小就会自动增长。

它最核心的特点就是:

大小可以动态变化。


2.2 vector和普通数组的区别

(1)普通数组的特点:

(1)大小固定
(2)定义后长度通常不能改变
(3)访问速度快
(4)语法简单

(2)vector的特点:

(1)大小可变
(2)可以动态增加元素
(3)同样支持下标访问
(4)内部仍然是连续空间,访问效率高
(5)更适合工程开发

所以你可以把vector理解为:

“比普通数组更灵活的升级版数组”。


2.3 vector为什么适合工程开发

因为vector解决了普通数组的几个痛点:

(1)长度可以动态变化
(2)自动管理内部内存
(3)支持很多现成操作
(4)和算法库配合方便,例如findsort

所以在工程里,如果你只是需要一个“能放很多同类型数据的线性表”,通常优先考虑vector


2.4 vector内部空间默认是什么状态

例如:

vector<int> datas;

这时候只是创建了一个vector对象,但它里面还没有元素

也就是说:

  • datas.size()为 0
  • 当前没有实际存储任何int元素

可以把它理解成:

先把“容器对象”建好了,但里面还没装数据。

当你第一次push_back()时,它才会根据需要去申请内部存储空间。

这个空间通常是分配在 堆区 的。

这里要注意一个表述:

并不是说“完全没有任何开销”,而是说:

不会一开始就按很大数组去申请空间,而是随着使用逐步申请。

这也是vector灵活的重要原因。


三、vector的定义与初始化

3.1 vector使用的是模板类型

vector的写法是:

vector<类型> 容器名;

这里的<类型>表示这个vector里要存什么类型的数据

例如:

vector<int> vi; vector<string> vs; vector<float> vf;

分别表示:

  • vi:存整数
  • vs:存字符串
  • vf:存浮点数

这就是模板的意义

同样一个vector容器,可以通过不同类型参数,存不同类型的数据。


3.2 vector的几种初始化方式

代码如下:

std::vector<int> vi; vector<string> vs; vector<float> vf; vector<int> vd1(10); //设置数组大小 vector<int> vd2{ 1,2,3,4,6 }; vector<string> vs1{ "ss1","ss2","ss3" };

下面分别解释。

(1)空vector

vector<int> vi;

表示定义一个空的int类型动态数组

此时:

vi.size()

结果为0


(2)指定初始大小

vector<int> vd1(10);

表示创建一个大小为 10 的vector<int>

注意:

这里不是“容量是10但没有元素”,而是已经有 10 个元素了,只是这些元素会被默认初始化

对于int来说,通常默认值为 0。

也就是说,这个vector逻辑上已经有 10 个位置可以通过下标访问:

vd1[0] ~ vd1[9]

(3)列表初始化

vector<int> vd2{ 1,2,3,4,6 }; vector<string> vs1{ "ss1","ss2","ss3" };

这表示在定义时直接给初始内容。

例如:

vector<int> vd2{ 1,2,3,4,6 };

里面一开始就有 5 个元素。


四、vector增加、修改与大小获取

4.1 push_back:在尾部追加元素

代码:

std::vector<int> datas; datas.push_back(10); datas.push_back(11); datas.push_back(12);

push_back()的作用是:

把元素追加到 vector 的最后面。

执行完后,datas的内容就是:

10 11 12

此时:

datas.size()

结果为3

所以push_back可以理解为:

尾插法、尾部追加元素。

这是vector最常用的增加元素方式之一。


4.2 size:获取当前元素个数

代码:

datas.size()

表示当前vector中有多少个元素。

要注意,size()反映的是当前实际元素个数,不是普通数组那种写死的长度概念


4.3 下标访问和修改元素

代码:

datas[0] = 99;

表示把第 0 个元素改为 99。

原本:

10 11 12

修改后变成:

99 11 12

这说明vector和普通数组一样,也支持:

容器名[下标]

进行访问。


4.4 使用下标访问时要注意什么

例如:

datas[0]

前提是datas里真的有第 0 个元素。

也就是说,下面这种写法是危险的:

vector<int> datas; datas[0] = 99; // 错误,越界

因为此时datas.size() == 0,根本没有元素 0。

所以要记住:

vector的下标访问,只能访问已经存在的元素。

如果你只是空定义了一个vector,一定要先push_back,或者先指定大小,再通过下标去改


五、vector的三种遍历方式

在实际开发中,vector最常用的操作之一就是遍历。

这里一共展示了三种遍历方法:

  1. 下标遍历
  2. 迭代器遍历
  3. C++11 范围 for 遍历

代码如下:

for (int i = 0; i < datas.size(); i++) cout << datas[i] << " "; cout << "\n"; //迭代器 std::vector<int>::iterator itr = datas.begin(); for (auto itr = datas.begin();itr != datas.end();itr++) cout << *itr << ","; cout << "\n"; //c++11 for (auto& d : datas) { cout << d << "|"; } cout << "\n";

下面分别讲。


5.1 下标遍历

代码:

for (int i = 0; i < datas.size(); i++) cout << datas[i] << " ";

这是最容易理解的一种方式。

(1)执行过程

假设:

datas = {99, 11, 12}

那么:

  • i = 0时输出datas[0]
  • i = 1时输出datas[1]
  • i = 2时输出datas[2]

最终输出:

99 11 12

(2)这种方式的优点

优点是非常直观,适合初学者理解。

同时,如果你还需要“当前位置下标”,那么这种方式非常方便。

例如:

cout << "下标:" << i << " 值:" << datas[i] << endl;

(3)这种方式的缺点

缺点是写法稍微繁琐,而且每次都要写:

datas[i]

如果只是单纯遍历所有元素,不一定是最简洁的方式。


5.2 迭代器遍历

这是vector很重要的知识点。

代码:

std::vector<int>::iterator itr = datas.begin(); for (auto itr = datas.begin(); itr != datas.end(); itr++) cout << *itr << ",";

(1)iterator是什么

iterator翻译过来就是:

迭代器

它可以理解为:

专门用来在容器中移动、定位和取值的一种工具类型。

对于vector这种连续存储的容器来说,迭代器的使用体验很像指针

比如:

  • 可以加*取值
  • 可以++往后移动
  • 可以和end()比较
  • 可以相减求距离

(2)这一句要怎么拆开理解

std::vector<int>::iterator itr = datas.begin();

可以拆成三部分。

1)std::vector<int>::iterator

表示:vector<int>这种容器对应的“迭代器类型”。

2)itr

表示:定义一个名为itr的变量。

3)datas.begin()

表示:把itr指向datas的第一个元素位置。

所以整句意思就是:

定义一个专门用于遍历vector<int>的迭代器变量,并让它先指向开头。


(3)begin 和 end 分别是什么

1)begin()
datas.begin()

表示指向第一个元素的位置。

2)end()
datas.end()

注意:

它不是最后一个元素,而是“最后一个元素的下一个位置”。

也叫:

尾后位置

这一点非常重要。

例如:

vector<int> datas{10,20,30};

那么:

  • begin()指向10
  • end()指向30后面的那个“越过末尾的位置”

所以遍历通常写成:

for (auto itr = datas.begin(); itr != datas.end(); itr++)

意思是:

从第一个元素开始,一直往后走,直到还没走到结尾的下一个位置


(4)为什么要写 *itr

代码:

cout << *itr << ",";

这里的itr是迭代器,它本身表示“位置”

*itr才表示:

取出这个位置上的元素值。

这和指针很像:

  • itr:像地址、像位置
  • *itr:像取地址里的值

(5)itr++是什么意思

itr++

表示把迭代器往后移动一个位置

对于vector来说,就是从当前元素走到下一个元素。

例如:

  • 一开始指向第 0 个元素
  • 执行itr++后,指向第 1 个元素
  • 再执行一次,就指向第 2 个元素

(6)为什么说vector迭代器很像指针

因为对于vector这种连续空间容器:

  • 可以*itr取值
  • 可以itr++往后移动
  • 可以做减法求位置差

例如:

f - datas.begin()

这就能算出当前位置是第几个元素

所以初学阶段,你可以先把vector迭代器理解成:

“一种行为很像指针的遍历工具”。


5.3 C++11范围for遍历

代码:

for (auto& d : datas) { cout << d << "|"; }

这是现代 C++ 里非常常用的写法。


(1)这句代码怎么理解

for (auto& d : datas)

意思是:

datas中的每一个元素,依次拿出来,当前这个元素用变量d来表示。

也就是说:

如果datas里有:

99 11 12

那么循环时:

  • 第一次,d代表99
  • 第二次,d代表11
  • 第三次,d代表12

(2)这里的d到底是什么

d就是“当前遍历到的元素”

你可以把它看成是循环过程中,系统自动帮你拿到的每一个值。

例如:

for (auto d : datas)

这里d就是一份拷贝值,是d这个临时副本,不会影响原来的datas

而你代码里写的是:

for (auto& d : datas)

这里d就不是拷贝,而是原元素本身的引用


(3)&引用是什么意思

&表示引用

引用可以理解为:

给原来的变量起一个别名。

例如:

int a = 10; int& b = a;

这时候b不是新开辟一个独立变量,而是a的另一个名字

所以:

b = 20;

实际上改的是a


(4)auto& d为什么常用

for (auto& d : datas)

这样写的好处有两个:

1)不会拷贝元素,效率更高
2)可以直接修改原容器中的元素

例如:

for (auto& d : datas) { d += 1; }

执行后,datas中每个元素都会加 1。


(5)如果不想修改元素怎么办

如果你只是读取,不想改值,工程里更推荐

for (const auto& d : datas) { cout << d << " "; }

这样既避免拷贝,也防止误修改原数据。


六、本节代码完整示例

#include <iostream> #include <vector> #include<string> using namespace std; int main() { //vector的定义及初始化 std::vector<int> vi; vector<string> vs; vector<float> vf; vector<int> vd1(10); //设置数组大小 //初始化 vector<int> vd2{ 1,2,3,4,6 }; vector<string> vs1{ "ss1","ss2","ss3" }; //增加\删除\修改\查找 { std::vector<int> datas; datas.push_back(10); //结尾处插入内容 datas.push_back(11); datas.push_back(12); datas[0] = 99; //直接修改 //三种遍历 for (int i = 0; i < datas.size(); i++) cout << datas[i] << " "; cout << "\n"; //迭代器 std::vector<int>::iterator itr = datas.begin(); for (auto itr = datas.begin();itr != datas.end();itr++) cout << *itr << ","; cout << "\n"; //c++11 for (auto& d : datas) { cout << d << "|"; } cout << "\n"; }

七、重要知识点

7.1 vector的核心特点

(1)vector是动态数组
(2)大小可以变化
(3)内部通常是连续空间
(4)支持快速访问
(5)工程中使用非常广泛

vector 就是一个可变长的数组容器,它既能像数组一样通过下标访问,也能通过迭代器和范围 for 更灵活地遍历。


7.2 本节必须掌握的几个操作

(1)定义vector<类型>
(2)使用push_back()增加元素
(3)使用size()获取大小
(4)使用[]下标访问与修改
(5)掌握三种遍历方式
(6)理解iteratorbegin()end()
(7)理解auto& dd&的含义


7.3 初学者最容易犯错的地方

(1)空vector直接用下标赋值

错误示例:

vector<int> datas; datas[0] = 99;

(2)把end()理解成最后一个元素

其实end()是尾后位置

(3)把迭代器当成元素值

其实迭代器是位置,*迭代器才是元素值

(4)不理解auto& d中的&

这里&是引用,不是取地址

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

3步解锁惠普OMEN全部性能:OmenSuperHub终极优化指南

3步解锁惠普OMEN全部性能&#xff1a;OmenSuperHub终极优化指南 【免费下载链接】OmenSuperHub 使用 WMI BIOS控制性能和风扇速度&#xff0c;自动解除DB功耗限制。 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否感觉自己的惠普OMEN游戏本性能被无形…

作者头像 李华
网站建设 2026/4/19 3:43:28

从Prompt Engineering到AST级重写:2026奇点大会独家披露——主流AI代码引擎的底层编译流程差异,为什么Copilot Pro在微服务重构中失败率高达41.6%?

第一章&#xff1a;2026奇点智能技术大会&#xff1a;AI代码对比 2026奇点智能技术大会(https://ml-summit.org) 核心对比维度 大会现场展示了三类主流AI编程助手在真实工程任务中的表现&#xff1a;GitHub Copilot X、Tabnine Enterprise v5.2 与开源模型CodeLlama-70B-Inst…

作者头像 李华
网站建设 2026/4/19 3:38:38

LinkSwift网盘直链下载助手:一键获取主流网盘高速下载链接的终极指南

LinkSwift网盘直链下载助手&#xff1a;一键获取主流网盘高速下载链接的终极指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 &#xff0c;支持 百度网盘 / 阿里云盘 / 中国移…

作者头像 李华
网站建设 2026/4/19 3:38:35

QuickRecorder终极指南:免费macOS录屏工具如何做到专业级体验?

QuickRecorder终极指南&#xff1a;免费macOS录屏工具如何做到专业级体验&#xff1f; 【免费下载链接】QuickRecorder A lightweight screen recorder based on ScreenCapture Kit for macOS / 基于 ScreenCapture Kit 的轻量化多功能 macOS 录屏工具 项目地址: https://git…

作者头像 李华
网站建设 2026/4/19 3:37:31

3分钟快速上手:手机号找回QQ号的终极完整指南

3分钟快速上手&#xff1a;手机号找回QQ号的终极完整指南 【免费下载链接】phone2qq 项目地址: https://gitcode.com/gh_mirrors/ph/phone2qq 你是否曾经因为忘记QQ号而无法登录&#xff1f;新手机到手想登录QQ&#xff0c;却只记得绑定的手机号&#xff1f;或者需要同…

作者头像 李华