C++ STL模板库6-string_view
string_view
是一种轻量级的字符串视图机制。 string_view
不管理内存,它只是现有字符串数据的视图或引用。避免了不必要的内存分配和复制。
std::string_view
是 C++17 标准引入的 STL 核心组件,定义于头文件 <string_view>
中,属于标准模板库(STL)的正式成员。
定义特性 🧩
定义位置 : <string_view>
头文件
命名空间 : std
命名空间下(与 std::string
同级)
模板类型 : 类模板:basic_string_view<charT, traits>
→ 特化 string_view
(char
)
非拥有式视图:仅持有原始字符串的指针和长度,不管理内存
- 需确保底层字符串生命周期长于
string_view
- 需确保底层字符串生命周期长于
零拷贝开销 🚀
操作成本等价于裸指针操作(编译期优化)
构造、子串操作,性能远优于
std::string
的复制操作// 使用 std::string(触发复制) std::string s = large_text; auto sub = s.substr(0, 30); // O(n) 复制开销 // 使用 std::string_view(零拷贝) std::string_view sv(large_text); auto sub_view = sv.substr(0, 30); // O(1) 仅设置指针和长度
兼容多种字符串类型
与
std::string
,const char*
,char[]
自动兼容#include <string_view> // 典型STL用法:构造string_view对象 std::string str = "Hello STL"; std::string_view sv(str); // 指向str数据的视图
常用操作 ⚙️
构造与赋值
std::string_view sv; // 空视图 std::string_view sv("Text"); // 直接初始化 sv = other_sv; // 赋值(浅拷贝)
元素访问
sv[i]
:无边界检查,高效但不安全。sv.at(i)
:越界抛std::out_of_range
异常。sv.front()
/sv.back()
:首尾字符 。
大小与容量
sv.size()
/sv.length()
:字符数(不含\0
)。sv.empty()
:判断是否为空视图。
子串操作
sv.substr(start_pos, length); // O(1) 复杂度,返回新视图
查找与比较
sv.find("sub")
:返回子串首次出现位置(失败时为sv.npos
)。sv.compare(other_sv)
:字典序比较(返回 0/正/负数)
使用注意事项⚠
生命周期管理
- 严禁持有临时字符串的视图(如函数返回的临时
std::string
)
auto bad_view = std::string_view(std::string("temp")); // 错误!临时对象销毁后视图无效 std::string_view create_view() { std::string temp = "Temporary"; return std::string_view(temp); // 错误!temp析构后视图失效 } // ❌ 返回悬垂指针
- 严禁持有临时字符串的视图(如函数返回的临时
无终止符
- 不以
\0
结尾,需通过size()
确定长度。传递到 C API 时可用sv.data()
,但需确保字符串本身有终止符。
char buf[] = {'A','B'}; // 不以\0结尾 std::string_view sv(buf, 2); std::cout << sv; // 安全(明确长度) // ❌ 错误:printf(sv.data()); // 可能越界
- 不以
修改限制
- 不可通过视图修改底层字符串内容(设计为只读视图)。
sv.remove_prefix(3); // ✅ 移动视图起点(string无此操作) sv.data()[sv.size()] = '\0'; // ❌ 非法写入(非可修改内存)
应用场景
函数参数传递
替代
const std::string&
或const char*
,避免隐式转换和复制:void process(std::string_view data); // 接收任意字符串类型
解析大文本
- 处理日志或文件时,用
string_view
截取子串无需复制内存。
解析大文本的子串,优先用std::string_view
代替std::string::substr
。
- 处理日志或文件时,用
兼容旧代码接口现代化
- 可隐式转换为
const char*
(需确保有终止符),适配传统 C 接口。
// 传统接口(引发拷贝) void process(const std::string& str); // 现代接口(兼容所有字符串类型) void process(std::string_view str); // ✅ 接受string/char*/字面量
- 可隐式转换为