尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

C++ STL 之 string_view 详解

C++ STL 之 string_view 详解
📅 发布时间:2026/7/4 4:25:52

C++ STL 之 string_view 详解

一、问题:字符串参数传递的隐形成本

在 C++ 中传递字符串最常见的方式是const std::string&,但每次传入const char*或字符串字面量时,都会隐式构造一个临时std::string对象——这意味着堆分配和字符拷贝。对于日志、配置读取、参数解析等高频路径,这个开销不可忽视。

voidparse(conststd::string&s);// 每次传 "hello" 都会构造临时 stringparse("hello world");// 隐式构造,O(n) 分配

二、方案:string_view 的设计与原理

std::string_view(C++17)是一个非 owning 的字符串视图,内部仅保存两个成员:指向外部字符数组的指针和长度。构造和拷贝都是 O(1),不涉及任何堆分配或字符拷贝。

#include<string_view>voidparse(std::string_view sv);// 零拷贝parse("hello world");// O(1),直接指向字面量

size = 11

string_view 对象

data 指针

size 长度

外部字符数组
const char*

'H']['e']['l']['l']['o'][' ']['W']['o']['r']['l']['d']

常用接口

std::string_view sv="hello world";sv.data();// 原始指针,不一定以 '\0' 结尾sv.size();// 长度,O(1)sv.empty();// 判空sv.front();sv.back();// 首尾字符sv[0];// 下标访问,无边界检查sv.at(0);// 下标访问,有边界检查(抛异常)sv.substr(0,5);// 返回另一个 string_view,O(1)sv.remove_prefix(6);// 去掉前 N 个字符sv.remove_suffix(5);// 去掉后 N 个字符sv.compare("hello");// 比较

C++20 新增:starts_with / ends_with

std::string_view sv="hello.cpp";if(sv.starts_with("hello")){/* 匹配 */}if(sv.ends_with(".cpp")){/* 匹配 */}

这两个函数在 C++20 之前需要手写sv.substr(0, 5) == "hello",既不直观也有性能浪费。对string_view和std::string均可用。

sv 字面量后缀

usingnamespacestd::string_view_literals;autosv="hello world"sv;// std::string_view,而非 const char*

"..."sv字面量在编译期直接构造string_view,零运行时开销。

三、string_view vs const string& 参数选型

函数形参一律用string_view,仅当:

场景推荐原因
只读访问字符串内容string_view零拷贝,兼容所有字符串类型
需要存储字符串副本std::stringstring_view 不 owning,拷贝后悬垂
需要\\0结尾的 C 风格接口const std::string&data() 不保证以\\0结尾
接口被广泛 ABI 暴露视情况string_view 按值传 16 字节,可能比 const ref 大
// 推荐:函数只读访问字符串voidlog(std::string_view msg);voidparse(std::string_view config);voidfind(std::string_view haystack,std::string_view needle);// 不推荐:函数需要持有副本voidset_name(std::string_view name){name_=std::string(name);// 必须显式转换}

经验法则:面向新代码时,函数形参中所有const std::string&都应当改为std::string_view,除非函数需要把字符串存入成员变量或需要\\0结尾。

四、悬垂指针风险

string_view不拥有字符数据,若底层字符数组被销毁,访问string_view就是悬垂指针。

std::string_view sv;{std::string s="temporary";sv=s;// sv 指向 s 的内部缓冲区}// s 销毁,sv 悬垂std::cout<<sv;// 未定义行为,可能崩溃或乱码

data 指向

data 悬垂指针

string_view sv

string s 的内部缓冲区

't']['e']['m']['p']['o']['r']['a']['r']['y']

s 析构后

缓冲区已释放

安全使用原则

// 正确:函数内临时使用,不跨语句存储voidsafe(std::string_view sv){autopos=sv.find('.');// 安全std::cout<<sv.substr(0,pos);// 安全}// 正确:传入静态数据staticconstexprautokConfig="version=1.0"sv;process(kConfig);// 安全// 错误:函数返回 string_view 指向局部 stringstd::string_viewbad(){std::string s="local";returns;// 悬垂!}// 正确:函数返回 string_view 指向静态数据std::string_viewgood(){return"static literal"sv;// 安全}

五、面试题(6 道)

1. string_view 的拷贝是深拷贝还是浅拷贝?

浅拷贝。仅复制指针和长度两个成员,O(1)。不复制字符数据。

2. string_view 的 substr 返回什么?是否分配内存?

返回一个新的string_view,指向原视图的子区间。O(1),无分配。

3. 以下代码的输出是什么?

std::string_view sv="hello";sv.remove_prefix(2);sv.remove_suffix(2);std::cout<<sv;

输出l。remove_prefix(2)去掉 “he”(span 变为 “llo”),remove_suffix(2)去掉 “lo”(span 变为 “l”)。

4. 为什么 string_view 不能作为 unordered_map 的 key?

string_view不 owning,无法保证 key 的生命周期。若底层字符串被销毁,map 中的 key 悬垂。需要用std::string作为 key。

5. const char* 转 string_view 是否安全?

安全,只要const char*指向的字符串在string_view使用期间有效。但要注意string_view不要求以\0结尾,sv.data()可能不是合法的 C 字符串。

6. string_view 能否替代 const std::string& 作为返回值?

不能。函数返回string_view时必须保证返回的字符串数据在函数返回后仍然存活——这极大限制使用场景。作为函数参数接收外部数据才是指定用法。

六、总结

特性string_viewconst string&
C++ 版本C++17C++98
构造复杂度O(1)O(n)(从const char*)
堆分配从不可能
生命周期跟踪不 owningowning
data() 以\0结尾不保证保证
substr 开销O(1)O(n)

string_view是现代 C++ 中字符串参数传递的首选类型。函数形参一律用string_view,返回值不用string_view返回局部字符串,记住这两条就能用好它。

相关新闻

  • 2007-2024年 供应链风险数据文本分析法 +文献
  • 音圈电机双闭环PID控制:提升精密定位性能的关键技术
  • 黑金古刀-永劫助手(BlackGoldAncientSword)——《永劫无间》战绩查询与队友识别桌面工具

最新新闻

  • 从理论到实践:gh_mirrors/yo/yolo_research中SwinTransformerV2注意力机制的应用详解
  • 一键修复与安装脚本:Linux服务器运维的自动化解决方案
  • Maven依赖管理完全教程:告别JAR包地狱的终极指南
  • ehentai-qt开发者指南:从源码结构到API调用的实战教程
  • nginx-auth-ldap核心参数解析:url、binddn与group_attribute配置技巧
  • 通往AGI的具身之路——TVA自适应协同进化系统(7)

日新闻

  • STM32F745VG与MC6470 IMU的高性能姿态控制系统设计
  • 机器不消费,人何以生存
  • AI项目操作手册编写规范与最佳实践

周新闻

  • Windows字体自定义终极方案:No!! MeiryoUI完全指南
  • Deepin Boot Maker:告别命令行,3分钟制作Linux启动盘的智能解决方案
  • Plain Craft Launcher 2:重新定义你的Minecraft游戏体验

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号