std::stoi 转换失败时抛 std::invalid_argument 或 std::out_of_range 异常;前者对应格式错误(如空字符串、纯字母),后者对应数值溢出(如超出 int 范围)。

stoi 转换失败时抛什么异常
std::stoi 在无法解析为有效整数时(比如空字符串、纯字母、超出 int 范围),会抛出 std::invalid_argument 或 std::out_of_range。前者对应格式错误,后者对应数值溢出——不是返回 0 或 -1,而是直接崩溃,除非你捕获。
必须用 try-catch 包裹 stoi 吗
是的,只要输入来源不可控(如用户输入、文件读取、网络响应),就必须用 try/catch。不加捕获的 stoi 在异常时会调用 std::terminate,程序直接退出。
- 安全写法:
try { int x = std::stoi(s); } catch (const std::invalid_argument&) { // 处理 "abc"、""、" " 等非数字内容 } catch (const std::out_of_range&) { // 处理 "99999999999999999999" 这类超大数 } - 注意:
std::stoi忽略开头空白,但遇到第一个非法字符就停;例如"123abc"会成功转成123,不抛异常 - 如果需要严格全匹配(不允许尾随字符),得自己检查剩余部分,比如用
std::from_chars或手动验证
stoi 和 from_chars 哪个更合适
如果你用的是 C++17 及以上,且在意性能和精确控制,std::from_chars 是更好选择:它不抛异常、不依赖 locale、能返回解析结束位置,还能区分“全匹配”和“部分匹配”。
-
stoi:简单场景够用,但开销略大(构造临时对象、异常机制) -
from_chars:零分配、无异常、支持更多整数类型(long long,unsigned),但需手动检查ec(std::errc)和指针偏移 - 示例:
int x; auto [ptr, ec] = std::from_chars(s.data(), s.data() + s.size(), x); if (ec == std::errc{}) { // 成功,且 ptr 指向解析结束位置 if (ptr == s.data() + s.size()) { // 全字符串都被消费 → 严格匹配 } }
常见误用:忽略负号或前导零的影响
stoi 默认按十进制解析,支持带符号("-42" 正确转为 -42),也接受前导零("0123" → 123),但不会当成八进制——除非显式传入基底参数 0 或 8。
立即学习“C++免费学习笔记(深入)”;
- 错误假设:
stoi("0123")得到 83(八进制)→ 实际是 123(十进制) - 要按八进制解析,必须写
stoi("0123", nullptr, 8)或stoi("0123", nullptr, 0)(自动识别前缀) - 十六进制同理:
stoi("0xFF", nullptr, 0)→ 255;但stoi("FF", nullptr, 16)也行 - 基底传 0 时,
"0x"、"0X"、"0"开头会分别触发十六、十六、八进制解析
stoi 的异常路径往往比转换逻辑本身更容易出问题——尤其当错误处理只打印一句日志就继续执行时,后续代码可能基于一个未定义值运行。宁可多写几行 catch,也不要靠“输入肯定合法”这种假设撑住逻辑。










