std::stoi 一用就崩溃是因为遇到非法字符抛 std::invalid_argument、超范围数字抛 std::out_of_range;必须用 try/catch 包裹,而 std::from_chars 更安全稳定,无异常、零分配,但需手动处理空格且不接受 std::string 直接传入。

std::stoi 为什么一用就崩溃?
因为 std::stoi 遇到非法字符(比如空字符串、纯空格、字母)会直接抛 std::invalid_argument;遇到超范围数字(如 "99999999999999999999")则抛 std::out_of_range。线上代码没包 try/catch 就等于埋雷。
- 必须用
try/catch包裹,不能假设输入干净 - 空字符串
""、全空白串" "、带单位的串"123px"都会触发异常 - 它默认只解析前缀数字,
std::stoi("123abc")返回123,但"abc123"就崩
std::from_chars 是不是更稳?
是,它是 C++17 引入的无异常、零分配、纯函数式方案,适合性能敏感或不允许异常的场景(比如嵌入式、游戏引擎底层)。
- 不抛异常,通过返回的
std::errc判断结果:std::errc::invalid_argument或std::errc::result_out_of_range - 要求输入是
std::string_view或裸指针+长度,不能直接传std::string—— 得写str.data(), str.size() - 不会跳过前导空格,
" 123"会被判为无效;需要自己用find_first_not_of(' ')截掉 - 示例:
int val; auto [p, ec] = std::from_chars(str.data(), str.data() + str.size(), val);
检查ec == std::errc{}才算成功
atoi 能不能用?
能,但极其危险——它对所有错误输入都默默返回 0,且无法区分 "0"、""、"abc" 这三种情况。
- 没有错误反馈机制,调试时根本看不出哪步错了
- 不支持指定进制(
std::stoi和std::from_chars都可以传base=16) - 仅建议用于临时脚本或已知绝对安全的内部数据流,生产环境回避
要不要自己写一个安全 wrapper?
如果项目里高频转换、又不想每次写 try/catch 或重复处理空格/边界,写一个轻量 wrapper 是值得的。
立即学习“C++免费学习笔记(深入)”;
- 封装点包括:自动 trim 前后空格、统一返回
std::optional<int></int>、可选进制参数、静默失败 or 记录日志开关 - 避免在 wrapper 里用
std::stoi—— 它的异常开销大;优先基于std::from_chars构建 - 注意
std::from_chars不处理符号溢出(如"-2147483649"在 32 位 int 下仍是std::errc::result_out_of_range),这点和std::stoi行为一致
真正麻烦的从来不是“怎么转”,而是“怎么确定转出来的数可信”。空格、符号、进制、截断、溢出、异常策略——每个点漏掉一个,线上就可能少一笔订单或多一条报警。










