C++ string 部分功能详解:迭代器、初始化与常用函数
在 C++ 中,string是处理字符串的核心容器,它封装了丰富的接口来简化字符串操作。本文将围绕string的迭代器访问、初始化方式、容量调整(reserve)、反转(reverse) 四大核心功能展开,结合可直接运行的代码和结果验证建议,帮你快速掌握string的实用技巧。
一、迭代器与范围 for:遍历 string 的两种核心方式
string作为 STL 容器的一种,支持迭代器(类似指针的访问工具)和范围 for 两种遍历方式,所有的STL容器都可以用以上两种方式遍历,其中范围 for 的底层本质就是迭代器。下面通过代码详细演示两者的用法。
1.1 迭代器遍历:灵活控制访问过程
迭代器的核心作用是 “指向容器元素”,支持*解引用获取值、++移动到下一个元素,适用于所有 STL 容器(如vector、list等)。注意:原文代码存在语法错误(如#include<iostrean漏写m、mainO错写括号、cout符号错误),以下是修正后的可运行代码:
cpp
#include <iostream> // 修正:补充<iostream>完整头文件 #include <string> using namespace std; // 修正:添加分号 int main() { string s = "asjhjksd"; // 待遍历的字符串 cout << "原字符串:" << s << endl; // 方式1:显式声明迭代器类型(string::iterator) string::iterator it = s.begin(); // begin()获取指向第一个元素的迭代器 cout << "显式迭代器遍历:"; while (it != s.end()) { // end()获取指向"最后一个元素的下一个位置"的迭代器 cout << *it << " "; // 解引用获取当前元素 it++; // 移动到下一个元素 } cout << endl; // 方式2:用auto简化迭代器类型(推荐) // 修正:auto自动推导为string::iterator,避免长类型书写 cout << "auto简化迭代器遍历:"; for (auto it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; return 0; } 1.2 范围 for:简化遍历的 “语法糖”
范围 for 专门用于 “遍历容器中所有元素”,无需手动控制迭代器的开始和结束,语法更简洁。其底层逻辑与迭代器完全一致,遍历过程是将s的元素逐个赋值给ch。
关键细节:如何用范围 for 修改字符串?
若直接写for (auto ch : s),ch是元素的 “拷贝”,修改ch不会影响原字符串;若在ch前加&(引用),则ch直接关联原字符串的元素,支持修改。
cpp
#include <iostream> #include <string> using namespace std; int main() { string s = "asjhjksd"; cout << "修改前:" << s << endl; // 1. 普通范围for(仅遍历,不修改) cout << "普通范围for遍历:"; for (auto ch : s) { cout << ch << " "; } cout << endl; // 2. 引用型范围for(支持修改原字符串) for (auto& ch : s) { // 关键:添加&,ch成为原元素的引用 ch = toupper(ch); // 将小写字母转为大写 } cout << "引用修改后:" << s << endl; // 输出:ASJHJKSD return 0; } 结果验证建议(图片内容)
运行上述两段代码后,截图应包含:
- 原字符串输出(如
asjhjksd); - 显式迭代器与 auto 迭代器的遍历结果(如
a s j h j k s d); - 引用型范围 for 修改后的大写字符串(如
ASJHJKSD)。
二、反向迭代器与传统访问:更多遍历选择
除了正向遍历,string还支持反向迭代器(从后往前遍历) 和数组式访问(用 [] 运算符),满足不同场景需求。
2.1 反向迭代器:从后往前遍历
反向迭代器通过rbegin()(指向最后一个元素)和rend()(指向 “第一个元素的前一个位置”)控制范围,++操作实际是 “向前移动”。
cpp
#include <iostream> #include <string> using namespace std; int main() { string s = "asjhjksd"; cout << "正向遍历:"; for (auto ch : s) cout << ch << " "; cout << endl; // 反向迭代器遍历 cout << "反向遍历:"; auto rit = s.rbegin(); // auto推导为string::reverse_iterator while (rit != s.rend()) { cout << *rit << " "; // 依次输出:d s k j h j s a rit++; // 反向迭代器的++是“向前移动” } cout << endl; return 0; } 2.2 传统数组式访问:借助 [] 运算符重载
string重载了[]运算符,允许像访问数组一样通过 “索引” 获取元素(索引从 0 开始),语法更符合 C 语言习惯。
cpp
#include <iostream> #include <string> using namespace std; int main() { string s = "asjhjksd"; cout << "数组式访问遍历:"; // size()获取字符串长度(元素个数) for (int i = 0; i < s.size(); i++) { cout << s[i] << " "; // 等价于*(s.begin() + i) } cout << endl; return 0; } 2.3 只读遍历:const 迭代器
若只需 “遍历不修改”,可在迭代器函数前加c(如cbegin()、crbegin()),获取const类型迭代器,避免误修改。
cpp
// const正向迭代器(只读) for (auto it = s.cbegin(); it != s.cend(); it++) { // *it = 'a'; // 报错:const迭代器不允许修改 cout << *it << " "; } // const反向迭代器(只读) for (auto rit = s.crbegin(); rit != s.crend(); rit++) { cout << *rit << " "; } 结果验证建议(图片内容)
截图应包含:
- 正向遍历结果(
a s j h j k s d); - 反向迭代器遍历结果(
d s k j h j s a); - 数组式访问结果(与正向遍历一致)。
三、string 的初始化:简洁的 “内置类型式” 写法
string的初始化方式有多种,最常用且直观的是拷贝初始化,语法与内置类型(如int)完全一致,降低记忆成本。
cpp
#include <iostream> #include <string> using namespace std; int main() { // 常用初始化:拷贝初始化(类似int a = 10;) string s1 = "zhdshk"; // 直接赋值字符串常量 cout << "s1: " << s1 << endl; // 其他常见初始化(补充参考) string s2; // 默认初始化:空字符串 string s3(s1); // 拷贝构造:s3是s1的副本 string s4(5, 'a'); // 填充初始化:5个'a',即"aaaaa" cout << "s2: " << s2 << "(空字符串)" << endl; cout << "s3: " << s3 << "(s1的副本)" << endl; cout << "s4: " << s4 << "(5个'a')" << endl; return 0; } 补充说明
更多初始化方式(如用字符指针、子字符串初始化)可参考cppreference.com或原文提到的cplusplus.com,文档中有详尽的参数说明。
结果验证建议(图片内容)
截图应包含 4 个字符串的输出:
s1: zhdshk;s2: (空字符串)(无内容);s3: zhdshk(与 s1 一致);s4: aaaaa。
四、reserve 函数:灵活调整 string 的容量
reserve(n)的核心作用是预分配字符串的容量(capacity),用于优化内存分配效率,不影响字符串的长度(size)和内容。理解size与capacity的区别是关键:
size:字符串当前的元素个数(实际存储的字符数);capacity:字符串在不重新分配内存的情况下,最多能存储的元素个数(底层数组的大小)。
4.1 reserve 的核心规则(原文重点)
- 若
n > 当前capacity:扩容到n(或更大,取决于编译器); - 若
n < 当前capacity:不强制缩容(是否缩容由编译器决定); - 若
n < 当前size:绝对不缩容(容量不能小于实际元素个数); - 不改变
size和字符串内容。
4.2 代码演示:reserve 的实际效果
以下代码基于原文test_string4()修正,直观展示reserve对size和capacity的影响:
cpp
#include <iostream> #include <string> using namespace std; // 测试reserve函数 void test_string4() { // 初始化一个较长的字符串 string s2("hello worldxxxxxxxxxxxxx"); // 内容:hello world + 11个x cout << "初始状态:" << endl; cout << "size: " << s2.size() << endl; // 输出实际字符数(11+11=22?需以运行结果为准) cout << "capacity: " << s2.capacity() << endl; // 编译器默认分配的容量 cout << "------------------------" << endl; // 1. reserve(20):n < 初始capacity(假设初始capacity>20) s2.reserve(20); cout << "reserve(20)后:" << endl; cout << "size: " << s2.size() << endl; // size不变 cout << "capacity: " << s2.capacity() << endl; // 可能不缩容(编译器决定) cout << "------------------------" << endl; // 2. reserve(40):n > 初始capacity s2.reserve(40); cout << "reserve(40)后:" << endl; cout << "size: " << s2.size() << endl; // size仍不变 cout << "capacity: " << s2.capacity() << endl; // 扩容到40(或更大) cout << "------------------------" << endl; } int main() { test_string4(); return 0; } 结果验证建议(图片内容)
以 GCC 编译器为例,截图可能包含:
- 初始状态:
size:22,capacity:31(编译器默认分配的容量通常略大于实际需求); reserve(20)后:size:22,capacity:31(不缩容);reserve(40)后:size:22,capacity:40(扩容到 40)。
五、reverse 函数:一键反转 string 或容器
reverse是 STL 算法库中的函数,支持对string、vector等容器进行反转,只需传入 “待反转范围” 的迭代器(左闭右开[begin, end))。
5.1 代码演示:反转 string
cpp
#include <iostream> #include <string> #include <algorithm> // 必须包含:reverse函数在<algorithm>中 using namespace std; int main() { string s = "hello world"; cout << "反转前:" << s << endl; // 反转:传入s的首尾迭代器(覆盖整个字符串) reverse(s.begin(), s.end()); cout << "反转后:" << s << endl; // 输出:dlrow olleh return 0; } 5.2 扩展:反转 vector
reverse同样适用于vector,用法完全一致:
cpp
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> v = {1, 2, 3, 4, 5}; cout << "反转前:"; for (auto num : v) cout << num << " "; reverse(v.begin(), v.end()); // 反转vector cout << "\n反转后:"; for (auto num : v) cout << num << " "; // 输出:5 4 3 2 1 return 0; } 结果验证建议(图片内容)
截图包含两部分:
- string 反转:
反转前:hello world,反转后:dlrow olleh; - vector 反转:
反转前:1 2 3 4 5,反转后:5 4 3 2 1。
总结
本文围绕string的核心功能展开,重点掌握:
- 迭代器(正向 / 反向、const)与范围 for 的遍历逻辑,尤其是引用型范围 for 的修改用法;
- 简洁的
string初始化方式,以及更多方式的查询渠道; reserve对容量的调整规则(不影响 size、缩容依赖编译器);reverse对容器的反转用法(需传入迭代器范围)。
string的接口远不止这些,若需深入学习,可访问cppreference.com或cplusplus.com,结合实际代码测试,才能真正熟练掌握。