安全转换应优先用std::from_chars:需手动跳过前导空白、传入连续内存范围、检查ec错误码及ptr是否完全解析;若用std::stoi则必须try-catch捕获invalid_argument和out_of_range异常,并验证解析位置。

std::stoi 会抛出异常,怎么安全转换?
直接调用 std::stoi 在遇到非法输入(如空字符串、纯空白、超出 int 范围)时会抛出 std::invalid_argument 或 std::out_of_range,生产代码里不能裸用。
- 先用
std::string的find_first_not_of(" \t\n\r")检查是否为空白串 - 再用
std::stol(返回 long)配合范围检查:若结果不在INT_MIN~INT_MAX内,就视为溢出 - 或者改用
std::from_chars(C++17 起),它不抛异常、只返回状态码,更适合关键路径
std::from_chars 怎么写才不踩坑?
std::from_chars 是目前最轻量、最可控的方案,但接口容易误用:它不跳过前导空格,也不处理尾随字符,必须手动清理。
- 调用前先用
str.find_first_not_of(" \t\n\r")找起始位置,跳过空白 - 传入的指针范围必须是连续有效内存,
std::string::data()在 C++11 后保证以 '\0' 结尾,但别直接传c_str()给from_chars—— 它需要的是迭代器式范围,不是 C 字符串 - 检查返回值
ec:等于std::errc::invalid_argument表示无有效数字;std::errc::result_out_of_range表示溢出;ec == std::errc{}才成功
std::string s = " 123abc";
auto start = s.find_first_not_of(" \t\n\r");
if (start == std::string::npos) return std::nullopt;
auto [ptr, ec] = std::from_chars(s.data() + start, s.data() + s.size(), result);
if (ec != std::errc{}) return std::nullopt;
为什么 atoi 不推荐用于新项目?
atoi 看似简单,但错误处理能力为零:输入非法时返回 0,无法区分 “0”、“”、“abc” 这三种情况,且不报告溢出(行为未定义)。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 它不提供任何错误信息,调用后无法判断转换是否真正成功
- 没有指定编码假设,对多字节或宽字符字符串完全不适用
- 在严格编译模式(如
-Werror=conversion)下可能触发警告 - 现代 C++ 工程中应视为遗留接口,仅用于兼容极老代码或嵌入式受限环境
带进制(如十六进制)的字符串怎么转?
std::stoi 和 std::from_chars 都支持进制参数,但行为差异大:前者自动识别 "0x" 前缀(当 base=0),后者必须显式指定 base 且不识别前缀。
立即学习“C++免费学习笔记(深入)”;
- 要解析
"0xFF"或"ff":用std::stoi(s, nullptr, 0),base=0 会按前缀自动选 16/10/8 - 要强制按十六进制解析(忽略前缀):用
std::stoi(s, nullptr, 16),此时"0xFF"会被当作 10 进制里的非法字符而失败 -
std::from_chars不识别前缀,std::from_chars(p, p+n, val, 16)只认纯十六进制字符,遇到'x'就停在那儿并设ec = invalid_argument
std::from_chars 是首选,但得自己处理空白和边界;如果代码不追求极致性能,封装一层带 trim 和异常捕获的 safe_stoi 更省心。别忽略前导空格和尾随垃圾字符——它们才是日常出错的主因。

















