You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++20 range-for循环中获取当前元素索引的lambda方案及其他新方法

C++20下range-for循环访问索引的实现方案

基于lambda的替代方案

你可以使用C++20的泛型lambda实现通用的带索引遍历工具,完全替代旧版的宏实现,没有宏的符号替换风险,类型完全安全:

// 通用带索引遍历lambda工具
constexpr auto indexed_for = []<typename Range, typename Func>(Range&& range, Func&& func) {
    std::size_t idx = 0;
    for (auto&& val : std::forward<Range>(range)) {
        func(idx, std::forward<decltype(val)>(val));
        ++idx;
    }
};

使用示例:

std::vector<int> vals = {10, 20, 30};
indexed_for(vals, [](std::size_t i, int& val) {
    // 直接使用索引i和元素val,支持读写
    val += i;
});

标准库原生实现方案

C++20引入的ranges库可以直接用std::views::zip + std::views::iota的组合实现带索引遍历,配合结构化绑定语法更加简洁,不需要自定义辅助工具:

std::vector<int> vals = {10, 20, 30};
for (auto [idx, val] : std::views::zip(std::views::iota(0u), vals)) {
    // 直接解包得到索引idx和元素引用val
    val += idx;
}

配合views::reverse的注意事项

两种使用场景对应不同的写法,没有额外运行时开销:

  • 如果需要遍历顺序的递增序号:先对原范围应用views::reverse再绑定索引,得到的序号从0开始随遍历顺序递增
  • 如果需要元素在原容器中的原始索引:先绑定索引再应用views::reverse,此时不管叠加任何范围适配器,得到的索引都对应元素在原容器中的原始位置
    示例(获取原始索引):
for (auto [idx, val] : std::views::zip(std::views::iota(0u), vals) | std::views::reverse) {
    // 第一个迭代到的是vals的最后一个元素,idx为vals.size()-1,符合原始索引预期
}

相比旧方案的优势

你之前常用的循环外额外声明索引变量的写法,存在索引作用域溢出、循环内使用continue时容易漏写索引递增的问题。上述C++20的方案将索引的作用域完全限制在循环内部,语法更干净,也避免了人为失误。


内容的提问来源于stack exchange,提问作者Tom Huntington

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 23:36:03