substr()截取末尾字符最稳妥,需先判断s.size()>=n再调用s.substr(s.size()-n),避免无符号下溢;n为0时返回空串;只读场景推荐string_view以避免拷贝。

用 substr() 截取末尾字符最直接
只要字符串长度 ≥ N,substr() 是最稳妥的选择。它不依赖迭代器、不触发额外内存分配,且语义清晰。
- 调用方式是
s.substr(s.size() - N),注意不是s.substr(-N)(C++ 不支持负索引) - 必须先检查长度,否则
s.size() - N会因无符号整数下溢变成极大值,导致std::out_of_range - 如果 N 为 0,
substr(s.size())返回空字符串,合法但需确认是否符合业务预期
处理长度不足时的常见错误
很多人写成 s.substr(s.length() - N) 然后 crash,根本原因是没意识到 size() 和 length() 返回的是 size_t(无符号),0 - 1 不是 -1,而是 18446744073709551615(64 位)。
- 正确做法:先判断
if (s.size() >= N) { return s.substr(s.size() - N); } else { return s; } - 也可以用有符号转换:
static_cast<long>(s.size()) >= N</long>,但不如直接比大小直观 - 别用
s.end() - N配合std::string(begin, end)—— 对短字符串容易越界,且不如substr语义明确
需要兼容 C++11 以前版本怎么办
substr() 自 C++98 就存在,所以无需降级。但如果你在用非常老的编译器(如 VC++6.0),std::string::size() 可能返回 unsigned int 而非 size_t,仍要小心减法溢出。
- 安全写法统一用:
if (N == 0 || N > s.size()) return s.substr(0, N > s.size() ? s.size() : N);—— 这其实等价于直接返回s,但逻辑更显式 - 避免手写循环从末尾往前拷贝,除非你明确需要 view 或 avoid copy(此时应考虑
std::string_view(s.data() + std::max(0L, static_cast<long>(s.size()) - N), N)</long>)
性能和 const 正确性要点
substr() 总是返回新字符串,有拷贝开销。如果只是读取、不修改,且 N 很大或字符串极长,std::string_view 更合适。
- 只读场景推荐:
std::string_view sv = s.size() >= N ? std::string_view(s.data() + s.size() - N, N) : s; - 注意
string_view的生命周期依赖原字符串,不能脱离s单独存在 - 如果函数参数是
const std::string&,返回std::string_view是安全的;返回std::string则必然拷贝
边界情况和隐式类型转换最容易被忽略——尤其是把 N 声明为 int 却和 size_t 直接相减。宁可多写一行判断,也不要靠“应该不会太短”来赌。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











