strlen会崩掉而std::string::length()不会,因为前者依赖'\0'结尾、越界读则未定义行为,后者直接返回内部记录的长度;二者length()与size()完全等价;仅对接C API时需用strlen,且须确保参数为有效null-terminated字符串。

为什么 strlen 会崩掉,而 std::string::length() 不会?
因为 strlen 只认 C 风格字符串——必须是以 '\0' 结尾的 char*;传进去一个没结尾的数组、局部 char 数组没初始化、或者 std::string 的 c_str() 被提前释放,它就直接越界读内存,行为未定义(可能 crash,也可能返回垃圾值)。std::string::length() 是对象自己记着长度的,不依赖结尾符,只要对象还活着,调用就安全。
常见错误现象:
- char buf[10]; strcpy(buf, "hello"); strlen(buf) → 看似没问题,但 buf 后面没显式补 '\0',实际取决于栈上残留数据
- const char* s = str.c_str(); str.clear(); strlen(s) → s 指向已失效内存,strlen 读到随机字节才停
- 把 std::vector<char></char> 或 std::array<char n></char> 直接传给 strlen → 没有 '\0' 就硬读,直到撞上段错误或巧合遇到零字节
std::string 的 length() 和 size() 有啥区别?
没有区别。两者完全等价,都返回字符个数(不是字节数),都是 O(1) 时间复杂度。C++ 标准明确要求 size() 与 length() 返回相同值,且不重新计算,只是内部成员变量的直接返回。
使用场景:
- 处理 UTF-8 字符串时,length() 返回的是字节数,不是“字符数”(即 Unicode code point 个数)
- 如果你用 std::u16string 或 std::u32string,length() 才接近逻辑字符数(仍需注意代理对)
- 判断空字符串:用 s.empty() 比 s.length() == 0 更清晰、更惯用
什么时候非得用 strlen?怎么用才不出事?
只有对接 C API 时才绕不开,比如 open()、printf()、syscall 参数,或老代码里一堆 char* 接口。别为了“性能”手写 strlen 替代 length()——现代编译器对 length() 优化极好,而 strlen 还要逐字节扫描。
安全用法要点:
- 确保源是真正的 null-terminated 字符串:用 strcpy 后检查是否写了 '\0',或用 strncpy 并手动补零
- 从 std::string 获取:只用 s.c_str(),且保证 s 生命周期长于 strlen 调用
- 对栈数组,显式初始化: char buf[256] = {}; 或 memset(buf, 0, sizeof(buf));
- 绝不传 std::string 对象本身、&s[0](除非确认以 '\0' 结尾)、或 data()(C++11 中 data() 不保证结尾零,C++17 起才等价 c_str())
宽字符和 UTF-8 下长度计算容易踩哪些坑?
strlen 和 std::string::length() 都只数字节,不管编码。UTF-8 里一个汉字占 3 字节,length() 就返回 3;wcslen 和 std::wstring::length() 数的是 wchar_t 个数,但 Windows 上 wchar_t 是 2 字节(UCS-2),无法表示所有 Unicode 字符,Linux/macOS 是 4 字节(UCS-4),又浪费空间。
立即学习“C++免费学习笔记(深入)”;
关键点:
- 不要用 strlen 判断中文字符串“有几个字”,它返回的是字节数
- std::string 存 UTF-8 时,length() ≠ 字符数,需要用 ICU、utf8cpp 或手动遍历判断 0x80–0xBF 字节来跳过 continuation bytes
- std::string_view 的 length() 行为和 std::string 一致,但不管理内存,传入前更要确认底层数据有效且 null-terminated(如用于 C 函数)
事情说清了就结束











