
std::string_view 是 C++17 引入的轻量级、只读、非拥有式字符串视图类型。它不复制、不管理内存,仅保存一个指向已有字符序列的指针和一个长度值——本质上就是一个“安全的 const char* + size_t”封装,专为高效读取而生。
为什么需要 string_view?
传统函数若用 const std::string& 接收字符串,遇到字面量(如 "hello")或 const char* 时,会隐式构造临时 std::string,触发一次堆分配和内容拷贝;而用 const char* 又丢失长度信息,需依赖 '\0' 终止符,且无法直接处理不含 '\0' 的内存块(如二进制协议中的字符串字段)。string_view 正好填补这个空白:
- 避免隐式构造临时 string → 零拷贝、零分配
- 自带长度,不依赖 '\0' → 可安全切片任意连续内存(如 substr、网络包 payload)
- 统一接口:能从 std::string、const char*、字符数组、字面量等直接构造
它到底存了什么?
内部结构极简,主流实现(libstdc++ / libc++ / MSVC)都类似:
const char* data_;
size_t size_;
立即学习“C++免费学习笔记(深入)”;
没有容量、没有分配器、没有析构逻辑、没有小字符串优化(SSO)。复制一个 string_view 就是复制两个机器字(通常共 16 字节),开销可忽略。
它不保证底层数据以 '\0' 结尾,也不负责生命周期——你传给它的内存必须在 string_view 使用期间持续有效。
典型高效用法
- 函数参数首选:代替 const std::string& 或 const char*,尤其适合日志、解析、配置读取等只读场景
- 子串操作无成本:sv.substr(5, 3) 仅调整指针和长度,不分配新内存
- 快速比较与查找:starts_with("HTTP/"), find(':'), compare(other) 全部基于原始内存遍历,无额外开销
- 兼容旧代码无缝升级:已有 const char* 接口可逐步替换为 string_view,调用方几乎无需修改
必须警惕的陷阱
-
悬空视图:不要绑定到局部 std::string 或临时对象。例如:
std::string_view sv = std::string("abc").substr(0,2);—— 临时 string 析构后,sv 指向野内存 - 生命周期由你负责:string_view 不延长所指数据的生命。推荐绑定到 static、全局、类成员或明确长生存期的对象
- 不能转成 C 风格字符串直接使用:data() 返回的指针不保证以 '\0' 结尾,传给 printf("%s", sv.data()) 可能越界;如需 C 字符串,应确保末尾有 '\0' 或改用 sv.to_string().c_str()











