最直接标准做法是用 for 循环配合 i += 2,起始索引和边界条件须匹配数组长度,避免越界;常见错误是写成 i
用 for 循环配合
i += 2最直接标准做法就是写一个普通
for循环,但步长不写i++,改用i += 2。注意起始索引和边界条件必须匹配数组长度,否则越界。常见错误是写成
i 或漏判奇数长度数组的最后一个有效索引。
- 起始索引通常为
0(取偶数位),也可从1开始(取奇数位)- 终止条件必须是
i ,其中 <code>n是数组大小,不能写成i 这类易错形式- 对
std::vector,用vec.size();对 C 风格数组,得提前知道长度,比如sizeof(arr)/sizeof(arr[0])int arr[] = {10, 20, 30, 40, 50}; size_t n = sizeof(arr) / sizeof(arr[0]); for (size_t i = 0; i <h3>用迭代器时别用 <code>std::next</code> 做步进</h3><p><code>std::next(it, 2)</code> 看似方便,但每次调用都重新计算地址,效率低;更重要的是,它不检查是否越界,容易引发未定义行为。</p><p>正确方式是手动推进迭代器,并在每次推进前检查是否到达 <code>end()</code>。</p>
- 不要写
it = std::next(it, 2)—— 它可能越过end()- 推荐用
std::advance(it, 2),但它也不自动校验边界,仍需你手动判断- 最稳妥的是每次只
+= 2后立刻比较:if (it != vec.end()) { ... }避免用
std::ranges::views::stride(C++23)踩兼容性坑
std::ranges::views::stride(2)确实语义清晰,但它是 C++23 特性,GCC 12/Clang 15 才开始支持,且需显式开启-std=c++23。很多项目还卡在 C++17/C++20。更隐蔽的问题是:它返回的是一个 lazy view,底层不复制数据,但如果原容器生命周期结束,view 就悬空。
- 仅当确定编译器版本、标准支持、且容器生命周期可控时才考虑
- 调试时无法直接打印 view 内容,得转成
std::vector或循环展开,增加排查成本- 对小数组或简单遍历,纯属杀鸡用牛刀
指针算术要小心对齐和类型大小
用指针遍历(如
int* p = arr; p )本质和 <code>for循环等价,但容易误以为“p += 2跳过两个字节”——其实跳过的是两个int单元,即2 * sizeof(int)字节。这点在处理
char数组或自定义结构体时尤其关键:步长含义完全取决于指针类型。
char*指针加 2 真的是跳 2 字节;int*加 2 是跳 8 字节(假设int为 4 字节)- 如果数组元素不是 POD 类型,指针算术可能不合法,优先用索引或迭代器
- 用
std::span(C++20)可兼顾类型安全与指针风格,但需确认标准支持情况实际写的时候,90% 的场景用第一个
for循环就够了。真正容易出问题的不是语法,而是边界判断——尤其是当数组长度为 0 或 1 时,i += 2后是否还满足i ,这个细节一疏忽就段错误。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!












