size_t递减时i>=0恒真导致死循环,因无符号回绕;应改用i>0或有符号类型,并注意输入失败后清缓冲区及索引越界检查。

循环中 size_t 递减时,i >= 0 永远为真
这是最典型的“条件看似合理、实则永远不终止”问题。因为 size_t 是无符号类型,当它从 0 继续递减,不会变成 -1,而是回绕到最大值(如 SIZE_MAX),导致 i >= 0 恒成立。
常见错误写法:
for (size_t i = 0; i >= 0; --i) { /* 死循环 */ }
正确做法是避开从 0 开始递减:
- 改用正向循环:
for (size_t i = 0; i - 倒序但起始为
n,终止条件用i > 0:for (size_t i = vec.size(); i > 0; --i),访问时用vec[i - 1] - 若必须用有符号索引且范围可控,直接用
int i—— 但注意不要用于超大容器(如vector元素数超过INT_MAX)
while 循环里变量没更新,或更新逻辑被跳过
条件依赖的变量在循环体中未修改,或被 break/continue 绕过,就会卡死。比如读取用户输入后忘记清缓冲区,导致下一次 std::cin >> x 失败,x 值不变,条件恒为真。
实操建议:
- 每次循环入口处检查控制变量是否已被修改;可加断言:
assert(x != old_x || "x not updated"); - 涉及输入时,失败后务必调用
std::cin.clear()和std::cin.ignore() - 避免在循环体内嵌套多个
if分支后遗漏更新语句;把变量更新放在循环末尾统一处理更可靠
遍历 vector 时用 operator[] 却没检查索引
vec[i] 不做越界检查,一旦 i >= vec.size() 就触发未定义行为——可能崩溃、数据错乱,甚至静默出错。
安全策略分场景:
- 调试/用户输入等不可控场景:用
vec.at(i),它会抛std::out_of_range - 性能敏感且逻辑确定安全:手动检查
if (i ,并缓存 <code>vec.size()到局部变量避免重复调用 - 用范围
for替代索引遍历:for (const auto& x : vec),彻底规避索引计算错误
字符串替换、位移等操作中 find / substr 的偏移没重算
比如循环调用 str.find(old_str, pos) 做全局替换,但 replace 后字符串长度变化,若仍用原 pos 继续查,要么重复匹配同一位置,要么漏掉重叠部分(如 "aaa" → "a")。
关键点:
- 每次
replace后,新起始位置应为pos + new_str.length()(不是pos + 1) - 空字符串
old_str必须提前判,否则find("")永远返回0,陷入死循环 - 对
substr调用前,先确认pos和len满足pos
越界问题本质不是“会不会发生”,而是“什么时候暴露”。很多错误在小数据、单线程、调试模式下完全不显现,一到生产环境或边界输入就崩。真正难防的,是那些你根本没想到要检查的地方——比如 size_t 下溢后还在拿它当数组索引用,或者 find 返回 std::string::npos 却直接喂给 substr。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











