优先用std::stoi并捕获异常;atoi不检查输入合法性,空串、非法字符串、溢出均返回0或极值,易掩盖错误。

直接结论:需要健壮转换时,优先用 std::stoi 并捕获异常;atoi 完全不检查输入合法性,出错只默默返回 0 或 INT_MAX/INT_MIN,极易掩盖逻辑错误。
为什么 atoi 在真实项目里基本不能用
atoi 是 C 风格函数,行为极其简单粗暴:
- 遇到首个非数字字符(包括空格、字母、符号)就立刻停止解析,不报错也不提示
- 输入为空字符串、纯空格、或完全非法(如
"abc")时,一律返回0 - 溢出时不触发任何错误机制,而是按实现定义行为(通常是返回
INT_MAX或INT_MIN),且无途径得知是否发生溢出 - 无法区分
"0"和"xyz"—— 两者都返回0,但语义天差地别
std::stoi 的异常类型和典型处理方式
std::stoi 在 C++11 起提供标准异常反馈,关键点在于它抛出的不是一种异常,而是三种不同含义的异常:
-
std::invalid_argument:输入不含任何有效数字(如""、" "、"hello") -
std::out_of_range:数字合法但超出int表示范围(如"99999999999999999999") - 不抛异常的情况:仅当字符串含前导空格 + 可选符号 + 至少一位数字(如
" -42abc"→ 返回-42,不报错)
实操建议:
立即学习“C++免费学习笔记(深入)”;
try {
int x = std::stoi(s);
// 成功
} catch (const std::invalid_argument& e) {
// 处理完全无效输入
} catch (const std::out_of_range& e) {
// 处理溢出(注意:这里 x 未被赋值)
}
想严格校验“整串必须是合法整数”?得自己补逻辑
std::stoi 默认允许尾部垃圾字符(如 "123abc" → 123),这在多数业务场景下是隐患。要确保整个字符串都被消费,需配合 std::stol 或手动检查:
- 用
std::stol+end参数获取解析结束位置,再判断是否到达字符串末尾 - 或先用
std::all_of检查是否全为数字/符号(注意处理负号和空格) - 更稳妥做法:用
std::from_chars(C++17),它不抛异常、返回解析位置与错误码,且明确支持“全部匹配”语义
性能差异其实可以忽略,别为这点速度放弃健壮性
atoi 确实比 std::stoi 略快(无异常栈展开、无 locale 处理),但差距通常在纳秒级。真实程序中,字符串转换极少是性能瓶颈;而一次未捕获的 atoi 错误导致的逻辑崩溃,排查成本远高于这点开销。
真正容易被忽略的是:很多开发者以为加了 if (s.empty()) 就安全了,却忘了 " "、"0x1F"、"1e5" 这些输入对 atoi 来说依然会返回 0 或随机值——而 std::stoi 会明确告诉你它们不合法。










