当前位置: 首页 > news >正文

C++ 中的 string

目录
  • 核心概念
  • 初始化与构造
  • 容量与属性
  • 元素访问与遍历
    • 访问单个字符
    • C 风格字符串
    • 遍历
  • 修改与操作
  • 查找与子串
  • 类型转换
    • 数值转字符串 std::to_string(value)
    • 字符串转数值
  • 现代化特性
    • C++17:std::string_view
    • C++20
  • 底层原理
    • SSO(Small String Optimization)
    • COW(Copy-On-Write)
  • 最佳实践
    • 参数传递
    • 性能优化
    • 安全性

本文首发于我的个人博客:Better Mistakes

版权声明:本文为原创文章,转载请附上原文出处链接及本声明。
由于技术迭代较快,文章内容可能随时更新(含勘误及补充)。为了确保您看到的是最新版本,并获得更好的代码阅读体验,请访问:

🍭 原文链接:https://bfmhno3.github.io/note/string-in-cpp/


std::string 是 C++ Standard Library 提供的标准类之一,这也是 C++ 开发中最常用的类之一,它本质上是对 C 风格字符串(char*)的封装,提供了自动内存管理和丰富的操作接口。

核心概念

std::string 位于 <string> 头文件中,本质上是对 std::basic_string<char> 的特化版本。

  • 头文件:#include <string>
  • 命名空间:std
  • 特点:动态管理内存,自动处理扩容,兼容 C 风格字符串。

初始化与构造

#include <string>
#include <vector>std::string s1;                     // 默认构造,空字符串 ""
std::string s2 = "Hello, World";    // 拷贝初始化
std::string s3("Hello, World");     // 直接初始化
std::string s4(5, 'A');             // 生成 "AAAAA"
std::string s5(s2);                 // 拷贝构造
std::string s6(s2, 1, 3);           // 子串构造:从索引 1 开始取 3 个字符 -> "ell"// C++11 及以后
std::string s7 = {'H', 'i'};        // 列表初始化

容量与属性

了解容量对于优化性能至关重要,特别是避免不必要的内存重分配。

|函数|说明|备注|
|size() / length()|返回字符数量|两者完全等价,一般用 size()|
|empty()|判断是否为空|推荐使用,比 size() == 0 语义更清晰|
|capacity()|当前分配的内存容量|通常 >=size()|
|reserve(n)|预分配 n 字节内存|避免 append 时的多次内存重分配|
|shrink_to_fit()|释放多余内存(C++11)|让 capacity 接近 size|

元素访问与遍历

访问单个字符

  • operator[]s[i]不检查越界,效率高,但越界为导致未定义行为。
  • at()s.at[i]检查越界,越界会抛出 std::out_of_range 异常。
  • front() / back():访问首尾字符。

C 风格字符串

  • c_str():返回 const char*,以 NULL 结尾。主要用于兼容旧式 C 接口(如 printf)。
  • data():C++11 前不保证 NULL 结尾,C++11 后与 c_str() 基本一致。

遍历

std::string s = "Hello, World";// 1. 基于下标
for (size_t i = 0; i < s.size(); ++i) { /* ... */ }// 2. 基于迭代器
for (auto it = s.begin(); it != s.end(); ++i) { /* ... */}// 3. 基于范围 for 循环(C++11,推荐)
for (char c: s) { /* ... */ }       // 值拷贝
for (char& c: s) { c = toupper(c) } // 引用修改

修改与操作

|操作|函数|示例|
|追加|+=append()push_back()|s += " World"|
|插入|insert(pos, str)|s.insert(0, "Hi ")|
|删除|erase(pos, len), pop_back()|s.erase(0, 3)|
|替换|replace(pos, len, str)|s.replace(6, 5, "C++")|
|清空|clear()|把 size 设置为 0,capacity 通常不变|
|截断/扩充|resize(n)|改变 size,多出的补默认值|

查找与子串

所有查找函数如果未找到,都会返回常量 std::string::npos(通常是 -1 的无符号形式,即最大的 size_t())。

std::string = "filename.txt";// 1. 查找 find
size_t pos = s.find(".");
if (pos != std::string::npos) {// 找到了
}// 2. 反向查找 rfind(找最后一个出现的位置)
size_t last_dot = s.rfind(".");// 3. 查找集合 find_first_of / find_first_not_of
// 查找第一个出现的元音字母
size_t v_pos = s.find_first_of("aeiou");// 4. 获取子串 substr
// 参数:substr(开始位置, 长度)
std::string name = s.substr(0, pos); // "filename"
std::string ext = s.substr(pos + 1); // "txt"(省略长度则取到末尾)

类型转换

需要包含头文件 <string>

数值转字符串 std::to_string(value)

std::string s = std::to_string(3.14); // "3.140000"

字符串转数值

  • std::stoi(s)int
  • std::stol(s)long
  • std::stod(s)double
  • 注意:这些函数会处理前导空格,但遇到非法字符会抛异常

现代化特性

C++17:std::string_view

std::string 是 “拥有者”,其拷贝开销大。std::string_view 只是一个 “观察者”(包含指针和长度),零拷贝。

函数参数尽量使用 std::string_view 代替 const std::string&,特别是当你只需要读取字符串内容时。

// 避免了临时 std::string 对象的构造和内存分配
void print_prefix(std::string_view sv) {i f(sv.substr(0, 3) == "Pre") { // substr 也是 O(1) 操作// ...}
}

C++20

填补了长期以来 C++ std::string 缺少高频接口的遗憾:

  • s.starts_with("prefix"):判断前缀
  • s.ends_with("suffix"):判断后缀
  • s.contains("sub"):判断包含

底层原理

SSO(Small String Optimization)

原理:为了避免短字符串频繁的堆内存分配(Heap Allocation),std::string 内部通常有一个小的栈缓冲区(通常 15 或 22 字节,取决于编译器实现)。

效果

  • 如果字符串很短(例如:"Hello"),直接存放在栈上对象内部,无 malloc,速度极快。
  • 如果字符串变长,才会在堆上分配内存,指针指向堆。

COW(Copy-On-Write)

在 C++11 之后已被废弃。现在的标准规定 std::string 不允许使用 COW。这意味着 std::string a = b; 一定会发生深拷贝(除非使用 std::move)。

最佳实践

参数传递

  • 只读不拥有:C++17 前用 const std::string&,C++17 后优先用 std::string_view
  • 需要修改:用 std::string&
  • 需要拥有权(Sink):可以直接传值 std::string 并配合 std::move

性能优化

  • 在循环中追加字符串前,先用 reserve() 预留空间(写在循环之前)。
  • 尽量避免在循环内部频繁构造 std::string
  • 换行符优先用 \n 而不是 std::endl(除非你需要立即刷新缓冲区)。

安全性

  • 永远不要对 c_str() 返回的指针进行 delete 操作。
  • string 对象被修改或销毁后,之前获取的 iterators、references 和 pointers(如 c_str() 的结果)可能会失效。

📢 写在最后

如果你觉得这篇文章对你有帮助,欢迎到我的个人博客 Better Mistakes 逛逛。

在那里我归档了更多高质量的技术文章,也欢迎通过 RSS 订阅我的最新动态!

http://www.jsqmd.com/news/188197/

相关文章:

  • 模型剪枝量化尝试:进一步压缩HunyuanOCR体积的可能性
  • 8.10 命名空间 作用域
  • 报错:OSError: [WinError 1455] 页面文件太小,无法完成操作
  • 华为云ModelArts适配可能性:公有云平台部署建议
  • 亲测好用10个AI论文网站,研究生高效写作必备!
  • CSS样式干扰识别吗?测试HunyuanOCR对网页截图的鲁棒性
  • 移动端适配问题:HunyuanOCR能否用于APP内集成?
  • Task02:数据库的基本使用(MongoDB)
  • 上下文纠错能力验证:HunyuanOCR是否具备语义校正功能
  • 2025年宁夏银川市有实力的岗亭源头厂家推荐排行榜,成品移动岗亭/值班岗亭/停车场岗亭/移动房屋,岗亭厂家推荐排行榜 - 品牌推荐师
  • 24 - 数据存储 - 向量数据库
  • Nginx反向代理配置:安全暴露HunyuanOCR 8000端口API
  • 边缘计算场景适用性:HunyuanOCR在IoT设备上的运行潜力
  • 2025知码狐北京集训
  • 车辆管理系统毕业论文+PPT(附源代码+演示视频)
  • OCR accuracy benchmark测试:HunyuanOCR vs PaddleOCR
  • JavaSE——while循环
  • 这可能是你见过最省钱的电梯调试方案
  • Obsidian笔记自动化:图片转文字并插入Markdown文档
  • 【数字信号去噪】基于matlab灰雁算法优化变分模态分解GGO-VMD数字信号去噪(优化K值 alpha值 综合指标 适应度函数包络熵)【含Matlab源码 14812期】
  • 低分辨率图像识别:HunyuanOCR在模糊画面下的稳定性
  • 视频字幕识别新方案:基于腾讯混元OCR的技术路径探索
  • 银泰百货卡套装回收全流程解析,专业平台让闲置变现金 - 京顺回收
  • WPS Office插件开发方向:内置AI文字识别功能探讨
  • React/Vue项目中引入HunyuanOCR:前后端分离架构整合思路
  • IPCC报告编写辅助:HunyuanOCR提取全球科研机构纸质研究成果
  • 清华镜像站之外的选择:高效获取腾讯混元OCR模型文件
  • 京东无人机配送:HunyuanOCR识别农村地区手写收件信息
  • 国际反诈联盟:HunyuanOCR分析跨境诈骗团伙使用的伪造文件
  • 邮件自动化:利用DeepSeek生成高效话术的全面指南