std::string_view 是轻量级只读字符串视图,仅存储指针和长度,避免拷贝;适用于函数参数接收字面量、std::string 或 C 字符串且只读场景,但需防范悬空指针和生命周期问题。

std::string_view 是什么,为什么能避免拷贝
它是一个轻量级的、只读的字符串“视图”,不拥有数据,只存指向字符的指针和长度。传参时只复制两个字段(指针 + size_t),比 std::string 拷贝整个堆内存快得多。
适用场景:函数参数接收字符串字面量、std::string、C 风格字符串等,且函数内部只读不修改。
常见错误现象:std::string_view 指向的原始内存提前释放,导致悬空(dangling)——比如返回局部 std::string 的 sv:
std::string_view bad() {
std::string s = "hello";
return s.substr(0, 3); // ❌ s 析构后,sv 指向已释放内存
}
怎么安全地用作函数参数
把 std::string_view 当作“只读字符串通用接口”来设计函数签名,兼容性远超 const std::string& 或 const char*。
立即学习“C++免费学习笔记(深入)”;
- 接受字面量:
foo("hello")→ 直接构造,零拷贝 - 接受
std::string:foo(s)→ 调用隐式转换,不拷贝内容 - 接受 C 字符串:
foo(cstr)→ 自动推导长度(注意:不含 \0 终止符,cstr必须以 \0 结尾,否则行为未定义)
参数差异:const std::string& 无法直接绑定字面量(需临时 std::string 构造),const char* 无法知道长度,易出界;std::string_view 兼顾长度安全与零开销。
哪些情况不能用 string_view
只要涉及“需要所有权”或“可能修改内容”,就不能用 std::string_view。
- 要拼接、追加、转小写等操作 → 必须用
std::string - 需要长期持有(比如存进容器、跨函数生命周期)→ 确保所指内存生命周期 ≥
string_view生命周期 - 从
std::string::c_str()构造 → 安全;但从std::string::data()构造并传给异步回调 → 危险(string可能在回调执行前被移动或析构) - 使用
substr()后再保存 → 新string_view仍依赖原内存,不是独立副本
和 const char*、const std::string& 的性能对比
在参数传递层面,std::string_view 是三者中唯一真正零拷贝且长度明确的选项。
性能影响:按值传递 std::string_view 是两个机器字大小(通常 16 字节),而 std::string 按值传至少是 24 字节(小字符串优化下)+ 堆分配开销;const char* 虽小但无长度,每次调用 strlen 就是 O(n)。
兼容性影响:C++17 起支持,老项目需确认标准版本;GCC/Clang/MSVC 主流版本都已稳定支持,但注意某些嵌入式 STL 实现可能阉割。
容易被忽略的是:string_view 的 data() 不保证以 \0 结尾,所以不能直接传给 C 函数(如 printf("%s", sv.data()) 可能崩溃)——必须显式加 \0 或改用 std::string 中转。









