最推荐std::stoi,语义清晰但需确保输入可信;strtol可精准控错和定位;atoi因无法区分0与错误而危险;std::from_chars零开销无异常但需C++17且不跳空白。

std::stoi 用得最多,但会抛异常
绝大多数情况直接用 std::stoi,它把 std::string 转成 int,语义清晰、标准库自带、不用额外依赖。
但它有个硬伤:输入非法(比如空串、纯字母、超范围)时直接抛 std::invalid_argument 或 std::out_of_range 异常。线上代码没包 try/catch 就崩。
- 只适合你**完全信任输入格式**的场景,比如解析配置文件里写死的数字字段
- 别在循环里反复调用它处理用户输入——异常开销大,且掩盖了校验逻辑
- 注意它会自动跳过开头空白,但遇到第一个非数字字符就停,
std::stoi("123abc")返回123,不报错
strtol 更底层,能精准控错和定位
需要知道“到底哪错了”或者“读到哪停了”,就用 C 风格的 strtol。它返回长整型,但关键是第二个参数 char** endptr —— 你能拿到解析终止位置。
比如验证字符串是否「整个都是合法整数」,就得靠它:
立即学习“C++免费学习笔记(深入)”;
const char* s = "123";
char* end;
long val = strtol(s, &end, 10);
if (*end != '\0' || end == s) {
// 不是纯数字,或为空串
}-
strtol不抛异常,错误全靠返回值和endptr判断,适合嵌入式或性能敏感场景 - 第三个参数是进制,别漏写
10,否则遇到"0x1A"会被当十六进制解析 - 它支持前导空格和正负号,行为和
std::stoi一致,但更透明
atoi 看似简单,实际最危险
atoi 是最短的写法,但也是最不该用的。它遇到非法输入直接返回 0,且**没有任何方式区分“真的就是 0”和“根本不是数字”**。
- 输入
""、"abc"、" "全都返回0,毫无提示 - 超范围也不报,比如
"999999999999999999999"可能返回INT_MAX或任意截断值 - 仅限快速原型或脚本式临时代码,生产环境禁用
std::from_chars(C++17)是未来方向,但要注意平台
这是目前唯一零开销、无异常、不分配内存、还能精确反馈结果的方案,返回 std::from_chars_result 结构体,含 ptr 和 ec(错误码)。
但它有硬限制:
- 只支持
char字符串,不能直接传std::string,得用s.data()和s.size() - MSVC 从 19.20(VS 2019)开始支持,GCC 从 7.1,Clang 从 7.0;老项目可能编译不过
- 不跳过空白,遇到空格立即失败,要自己 trim
典型用法:
std::string s = "42";
int val;
auto [ptr, ec] = std::from_chars(s.data(), s.data() + s.size(), val);
if (ec == std::errc()) {
// 成功,且 ptr 指向结尾,说明全匹配
}真正麻烦的不是选哪个函数,而是想清楚:你要的是“尽力转一个数”,还是“严格验证输入合规”。前者 std::stoi 够用;后者必须用 strtol 或 std::from_chars,并检查全部返回信息。漏掉 endptr 或忽略 ec,等于没校验。










