STL容器——string类
一、string是什么
String 本质是由多个字符组成的线性有序序列,是编程语言中专门封装字符数组的高级数据结构。
字符串:"hello"
底层存储:[ 'h' , 'e' , 'l' , 'l' , 'o' ]
和C语言中的char[ ]相似。
二、string的优点
在 C 语言中我们用 char* / char[]处理字符串,痛点非常多:
-
需要手动管理内存,容易内存泄漏;
-
字符串拼接、拷贝、查找、截取都要手写逻辑,代码冗余;
-
没有封装好的成员方法,易用性极差;
-
无法直接用运算符做字符串比较、拼接。
C++ STL 提供的 std::string,它本质是封装了字符动态数组的容器,完美替代原生字符数组:
- 自动管理内存,无需手动 malloc/free;
- 包含很多字符串操作函数;
- 支持迭代器、兼容 STL 常规用法;
- 支持运算符重载,拼接、比较极其简洁。
三、string 常见初始化方式
学习 string类,是离不开查阅文档的

| 名称 | 使用示例 | 功能说明 |
| default(默认构造) | string(); | 构造一个空字符串,长度为零个字符 |
| copy (拷贝构造) | string (const string& str); | 构造str的副本。 |
| from c-string(拷贝c 字符串) | string (const char* s); | 复制s指向的以null 结尾的字符序列。 |
使用示例
oid Teststring()
{
string s1; // 构造空的string类对象s1
string s2("hello string"); // 用C格式字符串构造string类对象s2
string s3(s2); // 拷贝构造s2
操作符operator=
#include <iostream>
#include <string>
int main ()
{
std::string str1, str2, str3;
str1 = "Test string: "; // c-string
str2 = 'x'; // single character
str3 = str1 + str2; // string
std::cout << str3 << '\n';
return 0;
}
//输出结果:
// Test string: x
四、string类对象的容量操作
获取长度、返回空间大小,判空,清空,预留空间,修改空间大小
| 名称 | 使用示例 | 功能说明 |
| ⭐size | str.size() | 返回字符串有效字符长度 |
| length | str.length() | 返回字符串有效字符长度 |
| capacity | str.capacity() | 返回空间总大小 |
| ⭐empty | str.empty( ) | 检测字符串是否为空串,是返回true,否则返回false |
| ⭐clear | str.clear( ) | 清空有效字符 |
| ⭐reserve | s.reserve(100); | 为字符串预留100空间 |
| ⭐resize | s.resize(10, 'x'); | 将有效字符的个数改成 |
注意:
clear()
-
作用:只清空有效字符,将
size()置为 0。 -
不会释放底层空间,
capacity()大小保持不变。
resize(size_t n) 与 resize(size_t n, char c)
-
共同作用:将字符串有效字符个数修改为 n 个。
-
区别:
-
resize(n):字符增多时,用数字“0”填充。 -
resize(n, c):字符增多时,用字符“c”填充。
-
-
规则:
-
n < 当前 size:截断字符串,
size变小,capacity不变。 -
n > 当前 size:扩展字符串,
size变大,capacity可能扩容。
-
reserve()
-
作用:为 string 预留底层空间。
-
特点:
-
不改变有效元素个数(size 不变)。
-
仅改变底层容量
capacity。
-
-
规则:
-
当参数大于当前
capacity时:扩大容量。 -
当参数小于等于当前
capacity时:不做任何改变,不会缩容。
-
使用示例
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "hello world";
// 1. size / length 获取有效字符个数
cout << s.size() << endl; // 输出:11
cout << s.length() << endl; // 输出:11
// 2. capacity 获取底层容量
cout << s.capacity() << endl; // 输出:15(不同编译器略有差异)
// 3. empty 判断是否为空
cout << s.empty() << endl; // 输出:0 0代表非空
// 4. reserve 预留空间,只改容量不改长度
s.reserve(100);
cout << s.capacity() << endl; // 输出:111
cout << s.size() << endl; // 输出:11
// 5. resize 改变有效长度
s.resize(5);
cout << s << endl; // 输出:hello
cout << s.size() << endl; // 输出:5
s.resize(10, '*');
cout << s << endl; // 输出:hello*****
cout << s.size() << endl; // 输出:10
// 6. clear 清空字符,容量不变
s.clear();
cout << s.size() << endl; // 输出:0
cout << s.capacity() << endl; // 输出:111
cout << s.empty() << endl; // 输出:1 1代表为空
return 0;
}
五、string类对象的访问及遍历操作
| 名称 | 使用示例 | 功能说明 |
|---|---|---|
| ⭐operator[] | s[0] | 返回 pos 位置的字符,const string 对象调用时返回 const char& |
| begin() end() | s.begin() s.end () | begin() 获取指向第一个字符的迭代器;end() 获取指向最后一个字符下一个位置的迭代器 |
| rbegin() rend() | s.rbegin () s.rend () | rbegin() 获取指向最后一个字符的反向迭代器;rend() 获取指向第一个字符前一个位置的反向迭代器 |
| 范围 for(C++11) | for (char ch : s) {cout << ch;} | 更简洁的遍历方式,底层等价于迭代器遍历 |
使用示例
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "Hello123";
// 1. 下标访问
cout << "s[0] = " << s[0] << endl; // 输出:s[0] = H
// 2. 普通迭代器
cout << "迭代器遍历: "; // 输出:迭代器遍历:
for (auto it = s.begin(); it != s.end(); ++it)
cout << *it; // 依次输出:H e l l o 1 2 3
cout << endl; // 换行
// 3. 反向迭代器
cout << "反向遍历: "; // 输出:反向遍历:
for (auto it = s.rbegin(); it != s.rend(); ++it)
cout << *it; // 依次输出:3 2 1 o l l e H
cout << endl; // 换行
// 4. 范围 for (最推荐)
cout << "范围for: "; // 输出:范围for:
for (char ch : s)
cout << ch; // 依次输出:H e l l o 1 2 3
cout << endl; // 换行
return 0;
}
六. string类对象的修改操作
尾插、查找、截取
| 名称 | 使用实例 | 功能说明 |
|---|---|---|
| push back | s.push_back('c'); | 在字符串后尾插字符c |
| append | s.append(" World"); | 在字符串后追加一个字符串 |
| ⭐operator+= | s += "str"; | 在字符串后追加字符串str |
| ⭐c_str | s.c_str(); | 返回C格式字符串 |
| ⭐find + npos | s.find('c'); | 从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置 |
| rfind | s.rfind('c'); | 从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置 |
| substr | s.substr(pos, n); | 在str中从pos位置开始,截取n个字符,然后将其返回 |
使用示例
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "Hello";
// 1. push_back:在字符串后尾插字符
s.push_back('!'); // 在末尾加 '!'
cout << s << endl; // 输出:Hello!
// 2. append:在字符串后追加一个字符串
s.append(" World"); // 追加 " World"
cout << s << endl; // 输出:Hello! World
// 3. operator+=(重点):追加字符/字符串,和 append 等价但更常用
s += "!!"; // 追加字符串 "!!"
s += '?'; // 追加字符 '?'
cout << s << endl; // 输出:Hello! World!!?
// 4. c_str(重点):返回C格式字符串(const char*)
const char* cstr = s.c_str();
cout << cstr << endl; // 输出:Hello! World!!?(和printf兼容)
printf("printf输出:%s\n", cstr); // 常用于C语言API交互
// 5. find + npos(重点):从pos位置往后找字符/字符串,返回下标;找不到返回npos
size_t pos = s.find('W'); // 从0位置往后找 'W'
if (pos != string::npos) { // 必须判断是否找到
cout << "'W'的位置:" << pos << endl; // 输出:7
} else {
cout << "未找到" << endl;
}
size_t notFound = s.find('x');
if (notFound == string::npos) {
cout << "'x'未找到,npos值为:" << string::npos << endl;
}
// 6. rfind:从pos位置往前找字符/字符串(反向查找)
size_t rPos = s.rfind('!'); // 从末尾往前找第一个 '!'
cout << "最后一个'!'的位置:" << rPos << endl; // 输出:13
// 7. substr:从pos位置开始,截取n个字符(不写n则截取到末尾)
string sub = s.substr(6, 5); // 从下标6开始,截取5个字符
cout << "截取的子串:" << sub << endl; // 输出:World
return 0;
}
七. string类非成员函数
运算符重载、“+”、“<<”,">>"
获取一行输入、字典序比较
| 函数 | 功能说明 | |
|---|---|---|
| operator+ | string c = a + " " + b; | 尽量少用,因为传值返回,导致深拷贝效率低 |
| ⭐operator>> | —— | 输入运算符重载 |
| ⭐operator<< | —— | 输出运算符重载 |
| ⭐getline | getline(cin, line); | 获取一行字符串(可包含空格) |
| ⭐relational operators | (s1 == s3) (s1 != s2) (s1 < s2) (s2 > s1) | 大小比较(按字典序) |
使用示例
#include <iostream>
#include <string>
using namespace std;
int main() {
// ------------------------------
// 1. operator+(不推荐)
// ------------------------------
string a = "Hello";
string b = "World";
string c = a + " " + b; // 不推荐:会多次深拷贝,效率低
cout << "operator+结果:" << c << endl;
// 推荐用 += 代替:
string d = "Hello";
d += " ";
d += "World";
cout << "推荐写法(+=):" << d << endl;
// ------------------------------
// 2. operator>>(输入运算符重载)
// ------------------------------
string input1;
cout << "请输入一个单词(operator>>):";
cin >> input1; // operator>> 默认以空格/换行分隔,只能读单个单词
cout << "你输入的单词:" << input1 << endl;
// ------------------------------
// 3. operator<<(输出运算符重载)
// ------------------------------
string output = "这是输出运算符测试";
cout << "operator<<输出:" << output << endl; // cout << string 就是调用 operator<<
// ------------------------------
// 4. getline(获取一行字符串)
// ------------------------------
// 注意:如果前面用过 cin >>,会残留换行符,需要先清空缓冲区
cin.ignore(); // 忽略上一次输入残留的换行
string line;
cout << "请输入一行文本(可以带空格):";
getline(cin, line); // 读取整行,包括空格,直到遇到换行符
cout << "你输入的整行:" << line << endl;
// ------------------------------
// 5. relational operators(大小比较)
// ------------------------------
string s1 = "apple";
string s2 = "banana";
string s3 = "apple";
cout << boolalpha; // 让bool输出true/false而不是1/0
cout << "s1 == s3 ? " << (s1 == s3) << endl; // true
cout << "s1 != s2 ? " << (s1 != s2) << endl; // true
cout << "s1 < s2 ? " << (s1 < s2) << endl; // true(按字典序比较)
cout << "s2 > s1 ? " << (s2 > s1) << endl; // true
return 0;
}
更多推荐
所有评论(0)