std::string
一、std::string
简介
std::string
是 C++ 标准库提供的字符串类,封装了动态管理的字符数组,功能比传统的 C 风格字符串(char*
)更强大、安全、易用。
属于头文件:
<string>
所在命名空间:
std
主要优点:
- 自动内存管理(不需要手动分配/释放)
- 提供丰富的字符串操作函数(拼接、查找、替换等)
- 与流(如
cin
/cout
)兼容性好 - 支持下标访问与迭代器
二、基本用法示例
cpp
#include <iostream>
#include <string>
int main() {
std::string s1 = "Hello";
std::string s2 = "World";
std::string s3 = s1 + " " + s2; // 拼接
std::cout << s3 << std::endl; // 输出:Hello World
std::cout << "字符串长度:" << s3.length() << std::endl;
std::cout << "第二个字符:" << s3[1] << std::endl;
return 0;
}
三、常用成员函数汇总(+ 示例)
方法 | 说明 | 示例 |
---|---|---|
.size() / .length() |
获取字符串长度 | s.length() |
.empty() |
判断是否为空 | if (s.empty()) |
.at(i) |
安全访问第 i 个字符(带边界检查) | s.at(0) |
.append(str) |
追加字符串 | s.append(" World") |
.insert(pos, str) |
插入子串 | s.insert(5, ",") |
.erase(pos, len) |
删除部分内容 | s.erase(5, 1) |
.replace(pos, len, str) |
替换部分内容 | s.replace(0, 5, "Hi") |
.substr(pos, len) |
截取子串 | s.substr(0, 5) |
.find(str) |
查找子串位置 | s.find("llo") |
.rfind(str) |
从后向前查找 | s.rfind("o") |
.compare(str) |
字符串比较(返回值类似 strcmp) | s.compare("abc") |
.c_str() |
转为 C 风格字符串(返回 const char* ) |
printf("%s", s.c_str()) |
四、遍历方式
cpp
std::string s = "Hello";
// 方式1:下标访问
for (size_t i = 0; i < s.size(); ++i)
std::cout << s[i] << ' ';
// 方式2:范围 for 循环
for (char c : s)
std::cout << c << ' ';
// 方式3:迭代器
for (auto it = s.begin(); it != s.end(); ++it)
std::cout << *it << ' ';
五、与 C 字符串的互转
cpp
std::string cppStr = "hello";
const char* cStr = cppStr.c_str(); // C++ -> C
std::string newStr(cStr); // C -> C++
六、注意事项
string::at()
带边界检查,安全但略慢;[]
不检查越界。- 与
std::getline(cin, s)
配合时注意清除输入缓冲区。 - 不要对
.c_str()
返回的指针进行修改,它是只读的。
七、实战小示例:字符串反转
cpp
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string s = "abcdefg";
std::reverse(s.begin(), s.end());
std::cout << s << std::endl; // 输出:gfedcba
}
std::string_view
一、std::string_view
:轻量字符串视图(C++17 起)
简介
std::string_view
是一个非拥有型的只读字符串引用,不分配内存、不复制数据,适用于传参和高效处理子串。
关键特性
- 快速,无拷贝(零开销)
- 支持与
std::string
类似的操作(如substr
,find
) - 生命周期由原始字符串控制,不能跨作用域使用
示例:
cpp
#include <iostream>
#include <string>
#include <string_view>
void greet(std::string_view name) {
std::cout << "Hello, " << name << std::endl;
}
int main() {
std::string full = "Alice Wonderland";
std::string_view sv = full.substr(0, 5); // "Alice"
greet(sv);
}
用于高性能接口设计,可避免大量
string
拷贝。
二、性能优化技巧(std::string)
1. 减少重复构造
避免 string
频繁复制、构造,尽量使用引用或 std::string_view
:
cpp
void process(const std::string& s); // 优于传值
2. 预分配容量 .reserve()
避免频繁扩容导致的内存复制:
cpp
std::string data;
data.reserve(1024); // 提前分配空间,避免多次 realloc
3. 避免 +=
拼接过多次(会触发多次 reallocation)
可改用:
cpp
std::ostringstream oss;
oss << "Name: " << name << ", Age: " << age;
std::string result = oss.str();
三、Unicode / UTF-8 字符处理(中文、Emoji等)
C++ std::string
本身对字符集不做解释,只是按字节存储。
示例:
cpp
std::string str = "你好"; // 实际为 6 个字节,不是 2 个字符
std::cout << str.length(); // 输出:6
推荐处理 UTF-8 的库:
库 | 特点 |
---|---|
utf8cpp | 轻量、纯头文件库 |
ICU(Intl Components for Unicode) | 功能强大,适用于多语言、排序等 |
C++20 char8_t / std::u8string |
新的 UTF-8 字符类型(现代C++,但库支持有限) |
使用 utf8cpp
示例(读取 UTF-8 字符):
cpp
#include <utf8.h>
std::string s = "你好世界";
auto it = s.begin();
while (it != s.end()) {
uint32_t cp = utf8::next(it, s.end());
std::cout << std::hex << cp << " ";
}
四、常见误区与调试建议
1. c_str()
返回的是 const char*
,不能修改其内容
cpp
char* p = s.c_str(); // 编译器可能允许,但是 UB(未定义行为)
2. 不要返回局部 string_view
cpp
std::string_view get_name() {
std::string tmp = "Tom";
return tmp; // ❌ tmp 销毁后 string_view 悬空
}
调试建议
- 使用
.data()
+.size()
查看原始字节内容 - 用
.substr()
替代手动字符切片(更安全) - 使用
std::u32string
处理 Unicode(每字符固定宽度)
总结:适用场景对比
功能需求 | 建议使用 |
---|---|
动态字符串、读写操作 | std::string |
只读子串、传参 | std::string_view |
跨平台 Unicode 处理 | utf8cpp 或 ICU |
UTF-16 / UTF-32 字符 | std::u16string , std::u32string |