std::string_view能避免拷贝是因为它不拥有数据,仅保存指向已有内存的指针和长度,切片时只调整指针与长度,不分配内存、不复制字符;但必须确保所指字符串生命周期长于其自身,否则引发未定义行为。

std::string_view 为什么能避免拷贝
因为 std::string_view 不拥有字符串数据,只存一个指向已有内存的指针 + 长度。切片(比如取子串)时,它直接调整起始指针和长度,不分配新内存、不复制字符。
常见错误是把它当成“更轻量的 std::string”来用——比如返回局部 std::string 的 substr() 转成 string_view,结果指向已销毁内存,触发未定义行为。
- 只对生命周期长于
string_view本身的字符串使用(如全局字符串字面量、const std::string&参数、堆上长期存活的字符串) - 别用
string_view包装临时对象的c_str()或data(),例如std::string("hello").c_str() - 注意空字符串字面量:
""是以\0结尾的静态数组,string_view可安全持有;但std::string().data()可能为nullptr(C++11 起未要求非空),不能直接传入
函数参数该用 const std::string& 还是 std::string_view
优先用 std::string_view 做只读输入参数,尤其当函数内部只读取、不转存、不需空终止符时。它能同时接受 const char*、std::string、std::string_view 和字符串字面量,且零拷贝。
但要注意兼容性:C++17 才引入 string_view,旧项目或需支持 C++14 的接口仍得用 const std::string&;另外,如果函数内部要调用 C 风格 API(如 fopen、printf),必须有空终止符,此时 string_view 无法直接用,得转成 std::string 或确保源数据以 \0 结尾。
立即学习“C++免费学习笔记(深入)”;
- 推荐签名:
void process(std::string_view s) - 避免重载爆炸:不用同时写
void f(const char*)、void f(const std::string&)、void f(std::string_view) - 若需空终止:
s.data()只在确定底层存储以\0结尾时才安全(如字符串字面量、std::string的c_str()),否则得用std::string(s).c_str()(有拷贝代价)
std::string_view substr() 的陷阱
string_view::substr() 看似和 std::string::substr() 一样,但它返回的新 string_view 依然指向原字符串内存——所以只要原字符串被销毁或重分配,所有派生出的 string_view 全部失效。
典型翻车场景:从 std::string 成员变量中切片并存为类内 string_view 成员;或者把 substr() 结果传给异步回调,而原字符串在回调执行前已离开作用域。
- 不要把
string_view当作“子字符串对象”长期持有,除非你能 100% 控制其引用源的生命周期 -
substr(pos, n)中n超出当前长度时,不会抛异常,而是自动截断到末尾——这和std::string::substr()行为一致,但更容易忽略越界风险 - 没有
find_first_of等“修改视图”的成员函数变体,所有查找操作只是返回索引,不改变自身状态
和 std::string 互转的时机与代价
从 std::string_view 构造 std::string 必然触发拷贝,这是唯一一次“付费”时刻。反过来,std::string::data() 和长度可直接构造 string_view,零成本。
关键判断点:是否需要所有权?是否要修改内容?是否要保证空终止?满足任一,就得转 std::string;否则尽量留在 string_view 上游处理。
- 安全转换:
std::string_view sv = str;(str是std::string) - 有拷贝转换:
std::string s(sv);或std::string s(sv.begin(), sv.end()); - 注意隐式转换:函数参数为
std::string时,传string_view会触发隐式构造,悄悄产生拷贝——此时应显式检查是否真需要std::string
最易被忽略的是:调试时打印 string_view,用 std::cout 没问题,但若误写成 <code>std::cout 且 <code>sv 不以 \0 结尾,就会打印出乱码或崩溃。










