C++ STL入门:vector与字符串流详解
2026/5/13 1:55:07 网站建设 项目流程

引言

在前面的文章中,我们系统学习了 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对每个元素执行操作。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询