std::from_chars是兼顾安全与性能的现代选择;std::stoi需try/catch处理异常且要检查解析位置;std::atoi无法区分合法0与非法输入,应避免在安全场景使用。

std::stoi 是最直接的选择,但必须处理异常;std::atoi 简单却无法区分合法 "0" 和非法输入;用 std::from_chars(C++17)才是兼顾安全与性能的现代做法。
为什么 std::stoi 容易 crash?
它在遇到空字符串、纯空白、或完全无效字符时会抛出 std::invalid_argument;超出 int 范围则抛 std::out_of_range。不捕获就直接终止程序。
实操建议:
- 始终用
try/catch包裹,别假设输入可控 - 注意
std::stoi会自动跳过前导空白,但遇到第一个非法字符就停——比如"123abc"返回123,不报错 - 若需严格匹配整个字符串(不允许尾部乱码),得手动检查转换后位置:
size_t pos; int val = std::stoi(s, &pos); if (pos != s.length()) { /* 尾部有未解析字符 */ }
std::atoi 看似简单,实际埋雷最多
它接受 const char*,所以常写成 std::atoi(s.c_str())。问题在于:输入为空、全空白、或非法时,它静默返回 0,无法区分 "0"、""、"abc"。
立即学习“C++免费学习笔记(深入)”;
实操建议:
- 绝不能单独依赖返回值判断成功与否
- 如果非用不可,务必先用
s.find_first_not_of(" \t\n\r")检查是否为空白串 - 永远不要在安全敏感或数据校验场景下用
std::atoi
C++17 起该用 std::from_chars
它是无异常、无内存分配、支持部分解析的底层接口,返回 std::from_chars_result,含 ptr(下一个未读字符地址)和 ec(错误码)。
实操建议:
- 需要包含
- 只支持
int、long、long long等整型,不支持short或自定义类型 - 示例:
int val; auto [ptr, ec] = std::from_chars(s.data(), s.data() + s.size(), val); if (ec == std::errc{}) { // 成功,且 ptr 指向第一个未转换字符 if (ptr == s.data() + s.size()) { /* 全部转换完 */ } } - 注意:
std::from_chars不跳过空白,输入必须是纯数字开头,否则直接返回std::errc::invalid_argument
真正难的不是选哪个函数,而是想清楚:要不要容错?要不要报告具体错误位置?是否允许尾部垃圾?这些决定了你该扔掉 atoi,还是给 stoi 加上位置检查,又或者直接升级到 from_chars 并自己处理空白和边界。











