
c weekly#知识地图 #最佳实践 #CPP17 各位老师好老师是山东对人的一个尊称就像称呼帅哥美女一样C周刊 c weekly第一期 EP01 开始了主题今天用一分钟讲清楚—面试官为什么爱问std::string_view。这一期我们将从零开始 一步步带你理解string_view背后的设计初衷、使用边界以及它如何在项目中为我们节省内存、提升性能。我们不讲枯燥的标准文档不抛出脱离工程的例子。相反我们将聚焦在真实项目案例分析1. 什么是string_view 与 string 有什么区别std::string_view is a C17 library type that provides a lightweight,non-owning reference to a sequence of characters数据结构代码语言javascriptAI代码解释Description•从定义看和原来的 string 没有任何区别都是一个指针 指向一个字符串•C17中我们可以使用std::string_view来获取一个字符串的视图 字符串视图并不真正的创建或者拷贝字符串•只有使用权力没有所有权不负责资源申请释放。算法操作substr 零拷贝 零内存分配图片•字符串切片substr不创建新对象仅生成视图 ➜ 零拷贝•函数参数传递无需构造临时字符串对象 ➜ 降低内存分配•std::string_view比std::string的性能要高很多2. 使string_view 有啥好处•✅ 高频操作字符串,零拷贝 零内存分配 ,性能提高10%•✅开发者来说修改一行代码,代码工作量不复杂双手赞同•✅对领导来说方案简单收益大, 绝对同意对比stringstring_view收益内存分配次数O(n)0完全消除内存拷贝量路径总长度0字节零拷贝解析延迟(1k QPS)4.2μs/op1.1μs/op降低74%CPU缓存命中率83%97%14%3. 举例行业案例使用场景使用场景OceanBase (OB)•自定义:ObString类 没有使用标准 std 库代码语言javascriptAI代码解释class ObString { int32_t length_; char* ptr_; }; ObLogExternalStorageCtx::init(const ObString uriRocksDB•自定义RocksDB 有自己的Slice类代码语言javascriptAI代码解释class Slice { const char* data_; size_t size_; };•使用场景 WriteBatch 时候Slice类和std::string_view 转换•CephFS•使用 c17 提供 string_view 代替string•场景 元数据 MDS 查找一个文件时候目录遍历Tikv:•在 TiKV 这种对性能要求极高的 KV 存储中大量的 key/value 是临时读取、比较、传递而非修改•TiKV 在访问 RocksDB 时通过 Rust 封装的 FFI 接口通过rocksdb::DB对底层数据读取时不会创建新的字符串而是传递指针和长度•使用切片可以极大减少内存分配、数据复制、GC 压力切片比较RustC17类型所有权不拥有不拥有内存分配无无拷贝行为零拷贝零拷贝用法slice 操作substr操作生命周期风险编译期保障安全存在悬垂引用风险4. 动手挑战卡4.1 系统设计Ceph MDS 路径解析场景输入/mnt/data/project1/report.docx 输出逐级路径 [mnt, data, project1, report.docx] 考点内容•STL 提供基本 API 是是否熟悉 find substr vectorstring•在日常工作用 有没有结果基础库代码•优化string_view的路径分割组件 保证零内存分配、无拷贝•最后一个report.docx 单词怎么出来的。 面试小陷阱•面试时候面试官会问你最近 5 年 是不是一直写代码你回答自然是•面试官说好他怎么知道你水平经常会结合项目出一个系统设计题目•刷题 不光有算法题目 还有系统设计题目,•掌握数据结构掌握算法最后应用到实际项目才算通过•都是经常遇到小问题一点都不难4.2 传统实现C11代码语言javascriptAI代码解释// 存在多次内存拷贝 std::vectorstd::string split_path(const std::string path) { std::vectorstd::string components; size_t start , end ; while ((end path.find(/, start)) ! std::string::npos) { if (end ! start) { components.push_back(path.substr(start, end - start)); } start end ; } // 最后一个单词 if (start path.length()) { // 再次拷贝 components.push_back(path.substr(start)); } return components; } // 调用示例 auto parts split_path(/volumes/project_data/user/docs/report.docx);问题1每个substr()调用触发堆分配小字符串优化失效于15字符2解析长路径/a/b/c/d/e/f产生6次内存分配拷贝3内存碎片加剧尤其高频操作4.3 C17实现代码语言javascriptAI代码解释std::vectorstd::string_view split_path_sv(std::string_view path) { std::vectorstd::string_view components; size_t start , end ; while ((end path.find(/, start)) ! std::string_view::npos) { if (end ! start) { // 零拷贝仅记录指针和长度 components.emplace_back(path.data() start, end - start); } start end ; } //最后一个单词 if (start path.length()) { // 零拷贝 components.emplace_back(path.data() start, path.length() - start); } return components; } https://www.cppreference.com/w/cpp/string/basic_string_view/find.html•小思考C std::string::npos 表示什么无符号类型 为什么不用-1 表示图片课后作业可选