下面对 C++ 标准库中 <string>
头文件所提供的 std::basic_string
(通常的 std::string
)及其相关非成员函数做一次系统、深入的梳理,包括类型定义、成员函数分类、使用示例、性能特性及实践建议。
一、概述
<string>
定义了模板类 std::basic_string<CharT,Traits,Allocator>
,以及常见的别名
using string = std::basic_string<char>;
using wstring = std::basic_string<wchar_t>;
using u16string = std::basic_string<char16_t>;
using u32string = std::basic_string<char32_t>;
basic_string
是可变长度、连续存储的字符序列,封装了 C 风格字符串的管理,同时提供了丰富的成员函数用于构造、访问、修改、查找、比较、格式化等操作。
底层保证字符数据在内存上连续,可与 C 接口 (.c_str()
)、算法库(如 <algorithm>
)或字节 I/O 高效互操作。
二、主要成员类型
template< class CharT,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT> >
class basic_string {
public:
using traits_type;
using value_type; // CharT
using allocator_type;
using size_type; // 通常为 std::size_t
using difference_type;
using reference;
using const_reference;
using pointer;
using const_pointer;
using iterator; // 随机访问迭代器
using const_iterator;
using reverse_iterator;
using const_reverse_iterator;
using const_pointer;
static constexpr size_type npos = size_type(-1);
// …
};
traits_type
:字符比较、拷贝、长度计算等底层细节(默认为 char_traits<CharT>
)。
allocator_type
:负责内存分配,可自定义分配策略。
npos
:查找失败时的返回值,表示 “无位置”。
三、构造与赋值
重载 含义 basic_string()
构造空串 basic_string(const CharT* s)
从 C 字符串拷贝 basic_string(const CharT* s, n)
拷贝 s 前 n 个字符 basic_string(size_type n, CharT c)
构造长度为 n,所有字符为 c basic_string(InputIt first, last)
区间构造 basic_string(const string& other)
拷贝构造 basic_string(string&& other)
移动构造 operator= (const string& other)
拷贝赋值 operator= (string&& other)
移动赋值 operator= (const CharT* s)
从 C 字符串赋值 operator= (CharT c)
赋值为单字符串 operator= (initializer_list<CharT>)
列表赋值
std::string s1; // ""
std::string s2("hello"); // "hello"
std::string s3(5, 'x'); // "xxxxx"
std::string s4 = std::move(s2); // s2 变空,s4 拥有 "hello"
四、元素访问
函数/操作 含义 边界检查 operator[](size_type pos)
返回对第 pos 字符的引用 无 at(size_type pos)
同上,但越界抛 std::out_of_range
有 front()
/ back()
首字符 / 末字符的引用 无 data()
/ c_str()
返回指向连续字符数组的指针,以 \0
结尾 — begin()/end()/rbegin()/rend()
迭代器访问 —
std::string s = "abc";
s[1] = 'B'; // "aBc"
char c = s.at(2); // 'c'
// 如果 at(3) 会抛出异常
五、容量相关
函数 含义 size()
/ length()
当前字符数 max_size()
理论最大可容纳字符数 capacity()
当前已分配内存能容纳的字符数 reserve(size_type n)
请求至少能容纳 n 个字符 shrink_to_fit()
尝试减小容量以匹配当前大小 empty()
是否为空串
std::string s = "hello";
s.reserve(100); // 减少后续扩容次数
std::cout << s.capacity();
s.shrink_to_fit(); // 收缩到正好5或实现允许的下限
六、修改操作(Modifiers)
函数 含义 clear()
清空 insert(pos, str_or_cstr_or_n)
在 pos 处插入字符串 erase(pos, n)
删除从 pos 开始 n 个字符 push_back(CharT c)
追加单字符 append(str_or_cstr_or_n)
追加字符串 pop_back()
删除末字符 replace(pos, n, str_or_cstr_or_n)
替换从 pos 开始 n 字符为新串 swap(string& other)
与 other 交换内容,常数复杂度
std::string s = "12345";
s.insert(2, "AB"); // "12AB345"
s.erase(4, 2); // "12AB5"
s.replace(2, 2, "CD"); // "12CD5"
s += "!"; // "12CD5!"
s.pop_back(); // "12CD5"
七、查找与比较
1. 查找(返回 size_type
or npos
)
函数 含义 find(str_or_cstr_or_c, pos)
从 pos 开始首次出现 rfind(...)
反向查找 find_first_of(chars, pos)
查找任一匹配字符 find_last_of(...)
反向查找任一匹配 find_first_not_of(chars, pos)
找到第一个不 在 chars 中的 find_last_not_of(...)
反向
std::string s = "foobar";
auto p1 = s.find("ob"); // 2
auto p2 = s.find_first_of("aeiou"); // 1 ('o')
auto p3 = s.rfind('o'); // 4
2. 比较(返回 -1, 0, +1)
int cmp = s1.compare(pos1, len1, s2, pos2, len2);
也可简化调用:
s1.compare(s2)
s1.compare(pos, len, cstr)
等价于 std::char_traits<CharT>::compare
,可用于排序或字典序判断。
八、子串与格式化
函数 含义 substr(pos = 0, len = npos)
返回从 pos 开始、长度为 len 的新 string
c_str()
/ data()
获取零结尾字符指针 resize(n, c = CharT())
改变长度,若扩展用 c 填充 copy(CharT* dest, n, pos)
将子串[ pos, pos+n ) 拷贝到 dest,不添加 \0
std::string s = "hello world";
std::string w = s.substr(6, 5); // "world"
char buf[6] = {};
w.copy(buf, 5); // buf = "world"
九、与流及格式化输出
#include <iostream>
#include <sstream>
std::string line;
std::getline(std::cin, line); // 读一行,包含空格
std::ostringstream oss;
oss << "Value=" << 123 << ", pi=" << 3.14;
std::string out = oss.str(); // "Value=123, pi=3.14"
支持 operator<<
、operator>>
(按空白分隔读入)
std::getline
读取整行(含空格)
std::to_string
, std::stoi
/stol
/stof
等函数在 <string>
中声明,用于数值与字符串互转。
十、非成员函数与互操作
函数 含义 std::to_string(numeric)
数值转字符串 std::stol
、std::stoi
…字符串转整数、浮点 std::getline(istream, string, delim)
以定界符读取 operator+ (s1, s2 or cstr)
字符串拼接 operator==, !=, <, >, <=, >=
字符串比较
std::string num = std::to_string(3.1415); // "3.141500"
int x = std::stoi("42"); // 42
std::string a = "foo", b = "bar";
auto c = a + "|" + b; // "foo|bar"
十一、性能与实践建议
避免不必要的 realloc
若能预估最终长度,应使用 reserve()
提前分配。
移动语义
对临时拼接结果或函数返回值,优先利用移动构造/赋值减少拷贝。
尽量使用迭代器与算法
与 <algorithm>
结合可做高效搜索、替换,如:std::replace_if(s.begin(), s.end(), [](char c){ return isspace(c); }, '_');
选择合适的查找函数
多次查找单字符可考虑 std::find
; 查找子串应优先 find(const char*)
;
对复杂模式可用正则(<regex>
)。
数值转换要捕获异常
std::stoi
等在失败时抛 std::invalid_argument
或 std::out_of_range
。
注意编码与字符集
跟多字节(UTF‑8)或宽字符混用时,std::string
仅按字节操作;对 Unicode 推荐用 <codecvt>
或第三方库。
通过以上对 <string>
头文件中 std::basic_string
的全面梳理与示例,帮助你在文本处理、格式化、搜索、性能优化等场景中高效、稳健地使用标准库字符串功能。祝编码顺利!