在C++23中,std::ranges::views::enumerate是一个范围适配器,它能把原范围中的每个元素包装成包含索引和值的tuple,从而在基于范围的for循环中直接拿到下标和元素,不需要额外定义计数器变量。

基本用法
使用enumerate时,需要用auto引用来接收每一次产生的pair-like对象,其中第一个成员是索引,第二个成员是元素的引用。下面以vector为例:
#include <iostream>
#include <vector>
#include <ranges>
int main() {
std::vector<int> nums = {10, 20, 30};
for (auto&& [index, value] : nums | std::views::enumerate) {
std::cout << index << ": " << value << "n";
}
return 0;
}
输出结果依次是0: 10、1: 20、2: 30。可以看到,index从0开始自动递增,value则是原容器中元素的左值引用,修改value会影响原容器。
与其他容器的配合
enumerate不仅支持vector,也支持任何可range的对象,比如string和array:
#include <iostream>
#include <string>
#include <ranges>
int main() {
std::string text = "abc";
for (auto&& [i, ch] : text | std::views::enumerate) {
std::cout << i << "=>" << ch << "n";
}
return 0;
}
和传统写法的对比
在C++23之前,常见的带索引遍历方式有两种:
- 用下标循环:for (size_t i = 0; i < v.size(); ++i)
- 用迭代器加距离:std::distance(v.begin(), it)
这两种方式要么需要关心容器长度,要么有额外计算开销。而enumerate作为懒求值的视图,不会复制容器,也不会产生距离计算代价。
返回值结构说明
enumerate产生的每个元素满足tuple-like约定,可以用结构化绑定拆解。其类型大致相当于:
| 成员 | 含义 |
|---|---|
| first | 从0开始的索引,类型通常是std::size_t或差类型 |
| second | 原范围元素的引用 |
注意事项
如果原范围是非const的左值,enumerate返回的value是可修改引用;如果原范围是临时对象,需要注意生命周期,避免悬垂引用。另外,enumerate本身不参与排序,它只记录迭代顺序中的位置。
enumerate适合顺序遍历场景,若需要过滤后再带索引,可写成 nums | std::views::filter(...) | std::views::enumerate。
综上,std::ranges::views::enumerate让C++的带索引遍历变得更简洁和安全,是现代C++范围库中的实用工具。
C++23std_ranges_views_enumerate带索引遍历修改时间:2026-07-27 11:51:22