stoi会直接崩溃,因其不预处理字符串,遇空串、纯空白或非数字开头即抛invalid_argument或out_of_range异常;须先检查有效字符,或改用from_chars/strtol等更稳健方案。

stoi 会直接崩溃?先检查字符串是否为空或只含空白
很多同学一用 stoi 就遇到 std::invalid_argument 或 std::out_of_range,其实八成是因为传了空串、全空格串,或者开头有不可见字符(比如 '\t' 或 BOM)。stoi 不做任何预处理,遇到非数字开头就立刻抛异常。
- 调用前用
str.find_first_not_of(" \t\n\r\f\v")找第一个有效字符,返回std::string::npos就说明是空/纯空白串 - 别依赖
str.empty()—— 它对" "返回false,但stoi仍会炸 - 如果业务允许宽松解析,改用
std::strtol更稳妥,它能通过endptr告诉你停在哪,还能区分“全无效”和“部分有效”
stoi 解析到哪为止?它只认最左连续数字,其余全丢
stoi 的行为不是“取整数部分”,而是“从首字符开始尽可能读数字,遇到第一个非数字字符就停”。比如 stoi("123abc") 返回 123,但 stoi("abc123") 直接抛 std::invalid_argument。
- 它不跳过前导字母,也不识别科学计数法(
"1e5"会被截成"1",然后停在'e') - 支持前导
'+'和'-',但仅限第一个字符;"-123abc"→-123,"--123"→ 异常 - 进制只能靠重载指定(
stoi(str, nullptr, 16)),默认是 10 进制,不会自动识别"0x"前缀
溢出时抛 out_of_range,但没告诉你具体超了多少
当字符串表示的数超出 int 范围(通常是 ±2147483647),stoi 抛 std::out_of_range。问题在于:它不返回截断值,也不提供原始数值大小线索,调试时很难定位是哪个输入导致的。
- 如果需要容错,别 catch 后随便给个默认值(比如
0),先记录原字符串,否则线上问题难复现 - 对可信度低的输入(如用户输入、日志解析),优先用
std::from_chars(C++17 起):它不抛异常,返回std::errc::result_out_of_range,且能精确指出解析到哪个位置 - 注意:
stoi溢出行为是未定义的(实际编译器多为抛异常),但不保证所有平台一致
替代方案选哪个?取决于你要不要异常、精度、还是跨平台兼容
不用 stoi 不代表要手写循环。不同场景下,更合适的工具其实是明确的:
立即学习“C++免费学习笔记(深入)”;
- 想静默失败、拿到解析长度 → 用
std::from_chars(C++17,无异常、零分配、最快) - 要兼容老标准(C++11)且接受异常 → 用
std::strtol,它返回long,可通过范围检查避免溢出误判 - 必须用
int且不怕异常 →stoi最简,但务必包在 try/catch 里,且 catch 要分invalid_argument和out_of_range - 别用
atoi—— 它对无效输入返回 0,无法区分"0"和"abc",错误诊断归零
真正麻烦的从来不是“怎么转”,而是“怎么知道转得对不对”。空格、溢出、前缀、编码——每个点都可能藏一个线上 bug,而 stoi 本身什么也不提醒。











