HOWTO · C++
遍历 C++ 中的列表
这是一个关于 List 数据结构以及我们如何在 C++ 中遍历 List 数据结构的简单教程。
本页内容
在 C++ 中遍历 std::list 时,先用 begin() 初始化迭代器;只要迭代器不等于 end(),就处理当前元素并递增迭代器。对迭代器解引用即可读取或修改当前值。循环会在到达 end() 之前结束;end() 是指向尾后位置的标记,并不指向最后一个元素。
C++ 中的 std::list 是什么?
std::list 是 C++ 标准库中的双向链表容器。它的元素存储在彼此链接的节点中,因此不像 std::vector 或数组中的元素那样占用一段连续内存。这种结构支持双向遍历;如果已经有指向某个位置的迭代器,在该位置插入或删除元素的时间复杂度为常数。
链表不支持 items[4] 这样的直接索引。按位置访问元素时,需要逐步移动迭代器,耗时与移动距离成正比。每个元素除了自身的值,还需要额外存储链接信息。如果需要在已知位置插入或删除元素,并希望迭代器保持稳定,可以选择 std::list;如果更需要紧凑存储或频繁按索引访问,vector 通常更简单。
C++ 还提供了另一种容器 std::forward_list。它是单向链表,只支持向前遍历,与 std::list 不同。有关背景信息,请参阅双向链表文章。
如何遍历 C++ 中的 std::list
begin() 返回的迭代器指向第一个元素。end() 指向最后一个元素之后的位置,因此可用作循环的结束条件,但不能对它解引用。递增迭代器即可移动到下一个元素。
运行下面的示例:
本节中的代码以及显示的标签或输出仍为英文。
#include <iostream>
#include <list>
int main() {
std::list<int> scores{12, 18, 25};
for (std::list<int>::iterator it = scores.begin(); it != scores.end(); ++it) {
std::cout << *it << '\n';
}
}
12
18
25
本节中的代码以及显示的标签或输出仍为英文。
这里,it 从 scores.begin() 开始。每次循环都会通过 *it 读取当前值,然后用 ++it 移动到下一个节点。当迭代器到达 scores.end() 时,条件不再成立,循环结束,不会读取尾后位置。
可以通过非 const 迭代器为 *it 赋值来修改元素。例如,在循环体中使用 *it += 1; 会使当前值增加 1。如果只需访问各个值,可以使用基于范围的 for 循环:for (int score : scores)。若要用这种方式修改值,请通过引用绑定每个元素:for (int& score : scores)。当需要使用迭代器本身时,例如删除当前位置的元素,应使用显式迭代器循环。
遍历过程中删除元素时,应将 erase 返回的迭代器赋回变量,以便从下一个元素继续。删除操作会使指向该元素的迭代器失效,但指向其他 std::list 元素的迭代器仍然有效。