HOWTO · C++

如何在 C++ 中循环遍历数组

本文介绍了如何在 C++ 中遍历数组中的元素。

本页内容

数组由固定数量的同类型元素组成。要逐个访问元素,可以根据任务需要选择循环:是否需要索引、是否要修改元素,或是否适合使用接受可调用对象的算法。下面的每个示例都定义了自己的数组和 main,因此可以分别编译为独立程序。(C++)

使用带索引的 for 循环

带索引的循环通过 i 提供当前位置。循环的三个表达式分别用于初始化索引、检查索引是否仍在数组范围内,以及在每轮结束后递增索引。这里使用 < count,因为含有五个元素的数组的有效索引是 0 到 4。

运行此示例:

本节中的代码以及显示的标签或输出仍为英文。

#include <iostream>

int main() {
    int values[] = {10, 20, 30, 40, 50};
    const int count = sizeof(values) / sizeof(values[0]);

    for (int i = 0; i < count; ++i) {
        std::cout << values[i] << ' ';
    }
    std::cout << '\n';
}
10 20 30 40 50

只要 values 仍是数组,sizeof 表达式就能计算出元素数量。如果将数组传给函数,它在函数中会被视为指针,因此应单独传入元素数量,或使用能够保存自身长度的容器。条件应以元素数量为界,并在每次迭代时将 i 递增一次,以免访问超出最后一个元素的位置。

使用 while 循环

当继续循环的条件比简单计数更复杂时,while 循环很有用。遍历数组时,应在循环前初始化索引,在访问元素前检查条件,并在循环体内递增索引。忘记更新索引可能导致循环无法结束。

运行此示例:

本节中的代码以及显示的标签或输出仍为英文。

#include <iostream>

int main() {
    int values[] = {5, 15, 25, 35};
    const int count = sizeof(values) / sizeof(values[0]);
    int i = 0;

    while (i < count) {
        std::cout << values[i] << ' ';
        ++i;
    }
    std::cout << '\n';
}
5 15 25 35

这种写法会按索引顺序访问元素。如果初始化、条件和更新操作适合放在一起,就使用 for 循环;如果条件或更新操作取决于循环中的其他工作,则可以使用 while。

使用基于范围的 for 循环

基于范围的循环会直接访问每个元素,无需显式写出索引。普通的 int value 会创建副本;当元素较小且循环只读取它们时,这种写法很合适。使用 const int& 可以避免复制,同时保持元素只读;如果循环需要修改原数组,则使用 int&。

运行此示例:

本节中的代码以及显示的标签或输出仍为英文。

#include <iostream>

int main() {
    int values[] = {1, 2, 3, 4, 5};

    for (const int& value : values) {
        std::cout << value << ' ';
    }
    std::cout << '\n';
}
1 2 3 4 5

例如,将循环变量改为 int& value 并为 value 赋值,就会更新数组中对应的元素。当需要按顺序处理每个元素,而不需要当前位置时,这种写法很简洁。

使用 std::for_each 遍历数组

std::for_each 是一种算法,而不是方法。它接收一个范围的起始迭代器、指向范围末尾后一位置的迭代器,以及一个会针对每个元素调用的可调用对象。使用该算法需要包含 <algorithm>;使用 std::array 则需要包含 <array>。

运行此示例:

本节中的代码以及显示的标签或输出仍为英文。

#include <algorithm>
#include <array>
#include <iostream>

int main() {
    std::array<int, 4> values = {2, 4, 6, 8};

    std::for_each(values.begin(), values.end(), [](int value) {
        std::cout << value * 2 << ' ';
    });
    std::cout << '\n';
}
4 8 12 16

此示例中的 lambda 就是可调用对象。它的 int value 参数会复制每个元素;如果可调用对象需要修改数组,可以使用 int& value。begin() 标记第一个元素,end() 标记最后一个元素之后的位置,因此算法会遍历整个范围。

根据任务选择循环

需要当前位置、比较相邻元素或控制索引步长时,可以使用带索引的 for 循环。如果由单独的条件决定何时停止遍历,则可以使用 while。若要直接、清晰地访问每个元素,可以选择基于范围的 for 循环;需要避免复制或修改元素时,应选择引用。如果将处理逻辑写成可调用对象适合算法式设计,则可以使用 std::for_each。这些形式都能遍历数组;应根据任务所需的信息和控制方式来选择,并确保索引始终处于数组的有效范围内。