C++ 标准库 string

下面对 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_stringstd::stoi/stol/stof 等函数在 <string> 中声明,用于数值与字符串互转。

十、非成员函数与互操作

函数含义
std::to_string(numeric)数值转字符串
std::stolstd::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"

十一、性能与实践建议

  1. 避免不必要的 realloc
    • 若能预估最终长度,应使用 reserve() 提前分配。
  2. 移动语义
    • 对临时拼接结果或函数返回值,优先利用移动构造/赋值减少拷贝。
  3. 尽量使用迭代器与算法
    • 与 <algorithm> 结合可做高效搜索、替换,如:std::replace_if(s.begin(), s.end(), [](char c){ return isspace(c); }, '_');
  4. 选择合适的查找函数
    • 多次查找单字符可考虑 std::find; 查找子串应优先 find(const char*)
    • 对复杂模式可用正则(<regex>)。
  5. 数值转换要捕获异常
    • std::stoi 等在失败时抛 std::invalid_argument 或 std::out_of_range
  6. 注意编码与字符集
    • 跟多字节(UTF‑8)或宽字符混用时,std::string 仅按字节操作;对 Unicode 推荐用 <codecvt>或第三方库。

通过以上对 <string> 头文件中 std::basic_string 的全面梳理与示例,帮助你在文本处理、格式化、搜索、性能优化等场景中高效、稳健地使用标准库字符串功能。祝编码顺利!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注