当前位置: 首页 > news >正文

C++ STL入门:vector与字符串流详解

引言

在前面的文章中,我们系统学习了 C++ 异常处理、IO 流体系等核心特性。从本文开始,我们将进入 C++ 标准库中最重要的组成部分——STL(Standard Template Library,标准模板库)的学习。

STL 包含三大核心组件:容器(Containers)、算法(Algorithms)和迭代器(Iterators)。本文将首先介绍字符串流(strstream)的用法作为过渡,然后深入讲解最常用的顺序容器——vector

第一部分:字符串流 strstream

一、什么是字符串流

字符串流是一种特殊的内存流,它以字符数组作为输入/输出的缓冲区。可以理解为把字符串当作文件来读写

#include <strstream> // 字符串流头文件(已废弃,但教材中常见) #include <sstream> // 现代 C++ 推荐的字符串流头文件

注意<strstream>在 C++98 中已被标记为废弃(deprecated),C++17 中彻底移除。现代 C++ 应使用<sstream>中的istringstreamostringstreamstringstream。但考虑到很多教材和旧代码仍在使用,本文会讲解两种方式。

二、输入字符串流 istrstream

从字符数组中读取数据,就像从文件中读取一样。

#include <iostream> #include <strstream> using namespace std; int main() { // 1. 创建字符流对象,绑定到字符数组 char buf[] = "123567"; istrstream iss(buf); // 2. 获取字符流的大小 iss.seekg(0, ios::end); // 移到末尾 streampos len = iss.tellg(); // 获取位置(即大小) cout << "字符流的大小: " << len << endl; // 3. 回到开头,逐个字符读取 iss.seekg(0, ios::beg); char c; int i = 0; while (i < len) { iss.get(c); cout << c; i++; } cout << endl; return 0; }

关键操作

操作说明
iss.seekg(0, ios::end)移动读指针到末尾
iss.tellg()获取当前读指针位置
iss.seekg(0, ios::beg)移动读指针到开头
iss.get(c)读取一个字符

三、输出字符串流 ostrstream

向字符数组中写入数据,就像向文件中写入一样。

#include <iostream> #include <strstream> #include <cstring> using namespace std; int main() { // 1. 创建足够大的缓冲区 char* bufp = new char[1024]{0}; ostrstream oss(bufp, 1024); int opt = 0; while (1) { // 检查缓冲区是否已满 if (oss.tellp() >= 1024) break; cout << "1.录入一行 2.打印所有 3.清空 0.退出\n"; cin >> opt; if (opt == 0) break; else if (opt == 1) { // 录入一行数据 cin.get(); // 清除残留的换行符 char line[32] = ""; cin.getline(line, 32); oss.write(line, strlen(line)); // 写入内容 oss.put('\n'); // 写入换行符 } else if (opt == 2) { // 打印所有行 cout << string(30, '-') << endl; istrstream iss(bufp, (int)oss.tellp()); while (!iss.eof()) { char line[32] = ""; iss.getline(line, 32); cout << line << endl; } } else if (opt == 3) { // 清空缓冲区 oss.seekp(0); // 写指针回到开头 memset(bufp, 0, 1024); // 清零 } } delete[] bufp; return 0; }

关键操作

操作说明
oss.write(buf, len)写入指定长度的数据
oss.put(ch)写入一个字符
oss.tellp()获取当前写指针位置(已写入的字节数)
oss.seekp(0)将写指针移回开头

四、字符串流的数据流向

五、现代 C++ 的替代方案(sstream)

#include <sstream> #include <string> // 输出字符串流 ostringstream oss; oss << "Hello" << 123 << 3.14; string result = oss.str(); // 获取写入的字符串 // 输入字符串流 istringstream iss("123 456 789"); int a, b, c; iss >> a >> b >> c; // 从字符串中格式化读取

第二部分:vector 容器

一、什么是 vector

vector是 C++ STL 中最常用的顺序容器,本质上是一个动态数组

二、基本操作

#include <iostream> #include <vector> using namespace std; int main() { // 1. 创建 vector vector<int> v1(10); // 10 个元素,默认值为 0 vector<int> v2(10, 5); // 10 个元素,初始值都是 5 // 2. 尾部插入 v1.push_back(10); v1.push_back(20); v1.push_back(30); // 3. 访问元素 cout << v1[0] << endl; // 下标访问(不检查越界) cout << v1.at(1) << endl; // at() 访问(检查越界) cout << v1.front() << endl; // 第一个元素 cout << v1.back() << endl; // 最后一个元素 // 4. 删除尾部元素 v1.pop_back(); // 5. 大小和容量 cout << "size: " << v1.size() << endl; // 元素个数 cout << "capacity: " << v1.capacity() << endl; // 当前容量 cout << "empty: " << v1.empty() << endl; // 是否为空 // 6. 清空 v1.clear(); // 清空所有元素,size=0 return 0; }

三、迭代器

迭代器是 STL 的核心概念,可以理解为泛化的指针

#include <iostream> #include <vector> using namespace std; int main() { vector<int> v1; v1.push_back(10); v1.push_back(20); v1.push_back(30); // 获取迭代器 vector<int>::iterator it1 = v1.begin(); // 指向第一个元素 vector<int>::iterator it2 = v1.end(); // 指向最后一个元素之后 // 使用迭代器遍历 for (vector<int>::iterator it = v1.begin(); it != v1.end(); ++it) { cout << *it << " "; // 解引用获取元素值 } cout << endl; // C++11 范围 for 循环(底层使用迭代器) for (int val : v1) { cout << val << " "; } return 0; }

迭代器类型

四、insert 与 erase

#include <iostream> #include <vector> using namespace std; int main() { vector<int> v1; v1.push_back(10); v1.push_back(20); v1.push_back(30); // 在指定位置插入 vector<int>::iterator it = v1.begin(); it = v1.insert(it, 8); // 在开头插入 8 v1.insert(it + 1, 7); // 在第二个位置插入 7 // 遍历打印 for (int val : v1) { cout << val << " "; // 输出: 8 7 10 20 30 } cout << endl; // 删除指定元素 v1.erase(v1.begin() + 1); // 删除第二个元素(7) // 删除范围 v1.erase(v1.begin(), v1.begin() + 2); // 删除前两个 return 0; }

insert 与 erase 的时间复杂度

操作位置inserterase
尾部O(1)O(1)
中间/头部O(n)O(n)

五、从数组创建 vector

#include <iostream> #include <vector> using namespace std; int main() { int arr[] = {1, 2, 3, 4, 5}; // 通过数组创建 vector vector<int> v1(arr, arr + 5); // arr → 数组起始地址 // arr + 5 → 数组结束地址(最后一个元素之后) // 遍历打印 for (vector<int>::iterator it = v1.begin(); it != v1.end(); ++it) { cout << *it << " "; } cout << endl; return 0; }

原理vector的构造函数接受两个迭代器参数,[first, last)左闭右开区间。

第三部分:STL 算法初探

一、for_each 算法

for_each是 STL 中最常用的遍历算法,对区间内的每个元素执行指定操作。

#include <iostream> #include <vector> #include <algorithm> // STL 算法头文件 using namespace std; // 普通函数作为操作 void show(int item) { cout << item << " "; } int main() { vector<int> v1; v1.push_back(1); v1.push_back(2); v1.push_back(3); v1.push_back(4); v1.push_back(5); // 方式1:传入函数指针 for_each(v1.begin(), v1.end(), show); cout << endl; // 方式2:传入 Lambda 表达式(C++11) for_each(v1.begin(), v1.end(), [](int item) { cout << item << " "; } ); cout << endl; return 0; }

for_each 的三要素

参数说明
v1.begin()起始迭代器
v1.end()结束迭代器
show/ lambda对每个元素执行的操作

二、vector 的构造与拷贝

#include <vector> using namespace std; int main() { vector<int> v1 = {1, 2, 3, 4, 5}; // 多种拷贝构造方式 vector<int> v2 = v1; // 拷贝构造 vector<int> v3(v1); // 拷贝构造 vector<int> v4(v1.begin(), v1.end()); // 迭代器区间构造 vector<int> v5(v1.begin(), v1.begin() + 3); // 部分拷贝 return 0; }

第四部分:vector 使用要点

一、常用成员函数速查表

函数功能时间复杂度
push_back(val)尾部插入O(1) 均摊
pop_back()尾部删除O(1)
insert(pos, val)指定位置插入O(n)
erase(pos)删除指定位置O(n)
clear()清空所有元素O(n)
size()元素个数O(1)
capacity()当前容量O(1)
empty()判空O(1)
front()第一个元素O(1)
back()最后一个元素O(1)
at(i)带越界检查的访问O(1)
operator[](i)不检查越界的访问O(1)
reserve(n)预留容量O(n)
shrink_to_fit()收缩到合适容量O(n)

二、vector 扩容机制

vector<int> v; v.reserve(100); // 提前预留 100 个元素的空间,避免频繁扩容 for (int i = 0; i < 100; i++) { v.push_back(i); // 这些操作不会触发扩容 }

扩容建议

  • 如果预知元素数量,使用reserve()提前分配

  • 扩容倍数通常是 1.5 或 2,具体取决于编译器实现

三、vector vs 数组

对比项原生数组vector
大小固定动态调整
越界检查at()有检查
拷贝需要手动 memcpy直接赋值
内存管理手动自动
与 STL 算法配合需要包装天然支持

总结

一、字符串流要点

要点说明
istrstream从字符数组读取
ostrstream向字符数组写入
seekg/tellg读指针定位
seekp/tellp写指针定位
现代替代stringstream<sstream>

二、vector 核心要点

三、一句话记忆

vector 是会自动扩容的数组,用push_back在尾巴加东西,用迭代器从头到尾遍历,用for_each对每个元素执行操作。

http://www.jsqmd.com/news/805884/

相关文章:

  • 2026年4月智能手表海关编码专业工具排行盘点:临时进口加征关税/化妆品海关编码/太阳能电池板海关编码/新能源汽车海关编码/选择指南 - 优质品牌商家
  • 医保结算避坑指南二:关于参保地统筹区划与直辖市划分及读卡应用技巧
  • 从零构建Kubernetes Operator:openclaw-operator实战解析
  • Scrapeless平台LLM对话数据抓取技能:一站式获取ChatGPT等主流AI模型结构化数据
  • 2026军队文职备考技术拆解:北京早起点教育军队文职、北京早起点教育咨询有限公司、北京早起点教育文职、北京早起点文职选择指南 - 优质品牌商家
  • Arm Forge性能分析工具在高性能计算中的应用与优化
  • 化学专业转AI,她不到两周拿到offer
  • 技术写作新姿势:用markmap.js.org在线工具,为你的开源项目README生成可视化架构图
  • GPT-J大模型在Graphcore IPU上的推理优化与部署实战
  • 2026宁国家装设计TOP5推荐:宁国别墅全案设计/宁国别墅装修/宁国别墅装饰/宁国别墅设计/宁国别墅软装设计/选择指南 - 优质品牌商家
  • 61.人工智能实战:Prompt 注入如何提前发现?从红队测试集到输入防护、输出校验与攻击样本回流
  • Fomu FPGA工作坊:从LED闪烁到RISC-V软核的微型硬件开发指南
  • 感统训练有必要吗?所有专注力差的孩子都需要做吗?
  • “人人都是产品经理”到“人人都是程序员”,是进步还是泡沫?
  • 基于大语言模型的股票研报自动化生成:技术架构与工程实践
  • 2026年5月新发布:深度解析成都顶尖尘推厂家的核心竞争力与选型策略 - 2026年企业推荐榜
  • 2026年Q2烟台空气能供暖市场剖析:为何华天成成为大型项目优选? - 2026年企业推荐榜
  • 开源市场平台架构解析:从技术栈选型到核心模块实现
  • 模型运行记录
  • 生产环境 Agent 总“抽风“?这套“人工 SOP + 大模型“混合架构让我省了 80% 的调试时间
  • AS3715 PMIC特性解析与便携设备电源设计实践
  • 内存加密技术与侧信道防御实践
  • 技术布道师(Evangelist):连接技术与大众的桥梁角色
  • 模块二-数据选择与索引——06. 列选择与操作
  • Rust异步运行时rustclaw:高性能任务调度与并发编程实践
  • 2026年最新盘点:为何宁波迪泰自动化设备有限公司是滚筒线专业工厂的首选 - 2026年企业推荐榜
  • Arm虚拟化内存管理:VTCR_EL2寄存器详解与实践
  • DollhouseMCP Collection:构建结构化AI能力库的完整指南
  • 物联网应届生,如何把不自信练没
  • classmcp:基于MCP协议的语义化CSS工具,提升AI前端开发效率