以下是 C++ 中 std::string
的详细解释,涵盖其特性、底层实现、常用操作及核心功能:
1. 基本概念
定义:
std::string
是动态字符序列,封装了字符数组,提供高效的字符串操作和内存管理。头文件:
#include <string>
核心特性:
动态大小:长度可动态增长,支持自动内存管理。
连续存储:字符在内存中连续存储,可通过指针直接访问(如
data()
)。兼容 C 字符串:可通过
c_str()
获取 C 风格字符串(const char*
)。丰富的操作:支持拼接、查找、替换、子串提取等高级功能。
2. 初始化与构造
(1) 空字符串
std::string s1; // 空字符串 std::string s2 {}; // 空字符串(C++11 统一初始化)
(2) 从 C 字符串构造
const char* cstr = "Hello"; std::string s3(cstr); // "Hello" std::string s4("World"); // "World"
(3) 从子串构造
std::string s5(s3, 1, 3); // 从 s3 的位置1取3个字符 → "ell" std::string s6("ABCDE", 3); // 取前3个字符 → "ABC"
(4) 重复字符构造
std::string s7(5, 'a'); // "aaaaa"
(5) 列表初始化(C++11+)
std::string s8 {'H', 'i'}; // "Hi"
3. 元素访问
(1) 下标访问
char c1 = s3[1]; // 不检查越界 → 'e' char c2 = s3.at(2); // 越界抛出 std::out_of_range → 'l'
(2) 首尾字符
char front = s3.front(); // 'H' char back = s3.back(); // 'o'
(3) 数据指针
const char* ptr = s3.c_str(); // 返回 C 风格字符串(以 '\0' 结尾) const char* data_ptr = s3.data(); // 返回字符数组(C++17 前可能不以 '\0' 结尾)
4. 常用操作
(1) 修改内容
操作 | 方法示例 |
---|---|
拼接字符串 | s3 += " World"; 或 s3.append("!"); |
插入字符 | s3.insert(5, " C++"); → "Hello C++" |
删除字符 | s3.erase(5, 4); → 删除从位置5开始的4个字符 |
替换子串 | s3.replace(6, 3, "Rust"); → 将位置6的3个字符替换为 "Rust" |
清空字符串 | s3.clear(); |
(2) 查找与子串
操作 | 方法示例 |
---|---|
查找子串 | size_t pos = s3.find("ll"); → 返回首次出现的位置(未找到返回 npos ) |
反向查找 | pos = s3.rfind("l"); |
提取子串 | std::string sub = s3.substr(1, 3); → 从位置1取3个字符 |
(3) 比较字符串
if (s3 == "Hello") { /* 相等 */ } if (s3.compare("Apple") > 0) { /* s3 字典序大于 "Apple" */ }
(4) 大小与容量
方法 | 说明 |
---|---|
s3.size() | 当前字符数(等价于 length() ) |
s3.empty() | 判断是否为空 |
s3.capacity() | 当前分配的内存容量(>= size() ) |
s3.reserve(100) | 预分配内存(减少扩容次数) |
s3.shrink_to_fit() | 释放多余内存(使 capacity() 接近 size() ) |
5. 迭代器与范围遍历
(1) 正向遍历
for (auto it = s3.begin(); it != s3.end(); ++it) { std::cout << *it; }
(2) 反向遍历
for (auto rit = s3.rbegin(); rit != s3.rend(); ++rit) { std::cout << *rit; }
(3) 范围 for 循环(C++11+)
for (char ch : s3) { std::cout << ch; }
6. 性能优化与底层实现
(1) 内存管理
短字符串优化(SSO):短字符串(通常 ≤15字符)直接存储在对象内部,避免堆分配。
动态扩容:当长度超过容量时,按一定策略(如倍增)重新分配内存并拷贝数据。
(2) 高效操作建议
预分配内存:频繁拼接时使用
reserve()
减少扩容开销。避免临时对象:使用
operator+=
或append()
代替+
拼接(+
生成临时对象)。// 高效拼接 std::string result; result.reserve(100); result += "A"; result.append("B");
7. 示例代码
#include <string> #include <iostream> int main() { std::string s = "Hello"; s += " World"; // "Hello World" s.insert(5, " C++"); // "Hello C++ World" s.replace(6, 3, "Rust"); // "Hello Rust World" size_t pos = s.find("Rust"); if (pos != std::string::npos) { std::cout << "Found 'Rust' at position: " << pos << std::endl; } std::string sub = s.substr(6, 4); // "Rust" std::cout << sub << std::endl; // 输出 "Rust" return 0; }
8. 注意事项
编码问题:
std::string
存储的是char
,适合处理 ASCII 或 UTF-8 字符串。如需处理宽字符(如 UTF-16),应使用std::wstring
。迭代器失效:修改字符串(如插入、删除)可能导致迭代器失效。
C 字符串陷阱:
c_str()
返回的指针在字符串修改后可能失效。const char* p = s.c_str(); s += "!"; // p 可能失效
9. 与 std::vector<char>
对比
特性 | std::string | std::vector<char> |
---|---|---|
设计目的 | 专为字符串优化 | 通用字符容器 |
特有方法 | find , substr , c_str 等 | 无 |
短字符串优化 | 通常支持 | 通常不支持 |
结尾字符 | 自动维护 \0 (通过 c_str() ) | 不自动添加 |
10. 适用场景
文本处理:解析、格式化、搜索替换等。
文件 I/O:读写文本文件内容。
网络通信:处理 HTTP 请求、JSON 数据等。
配置管理:存储键值对、路径等字符串数据。
总结
std::string
是 C++ 中处理字符串的核心工具,集高效性、安全性和易用性于一身。熟练掌握其操作可显著提升代码质量,尤其在需要动态字符串管理的场景中,它比原生字符数组更安全,比 vector<char>
更专业。
系统当前共有 438 篇文章