Skip to content

📦 06. STL 初探

一、什么是 STL?🤔

STL(Standard Template Library,标准模板库) 是 C++ 标准库的核心组成部分,它提供了一组现成的容器算法迭代器

简单来说:STL 就是 C++ 给你准备好的"工具箱"

想象一下,你要造一个书架:

  • 没有工具箱:你得自己锯木头、自己炼铁做钉子、自己磨刨子……
  • 有了工具箱:直接从盒子里拿出电锯、钉枪、刨子,开工!

STL 就是这个"工具箱"——别人已经写好了最高效的数据结构和算法,你直接拿来用就行。

为什么要学 STL?

手写使用 STL
自己写排序,可能 bug 一堆sort(arr, arr+n) 一行搞定
自己写动态数组,容易内存泄漏vector<int> v 自动管理内存
手动复制字符串,麻烦string s = "hello" 直接赋值
自己写链表,各种指针绕晕list<int> l 双向链表直接插入删除

NOTE

STL 的代码经过了数十年的优化和测试,比你手写的绝大多数实现更高效、更可靠。学会使用 STL 是 C++ 学习的重要里程碑。

二、vector —— 动态数组 🧩

1. 什么是 vector?

vector 是一个可以自动扩容的数组。与普通数组不同,它不需要事先指定大小,可以随时添加或删除元素。

cpp
#include <iostream>
#include <vector>  // 使用 vector 需要包含这个头文件
using namespace std;

int main() {
    // 创建 vector
    vector<int> v;         // 空的 vector
    vector<int> v2(5);     // 包含 5 个元素,默认都是 0
    vector<int> v3(5, 10); // 包含 5 个元素,都是 10
    vector<int> v4 = {1, 2, 3, 4, 5};  // 直接初始化

    cout << "v3: ";
    for (int i = 0; i < v3.size(); i++) {
        cout << v3[i] << " ";  // 像普通数组一样访问
    }
    cout << endl;

    return 0;
}

2. 常用操作

cpp
#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v;

    // 添加元素
    v.push_back(10);   // 在末尾添加 10
    v.push_back(20);   // 在末尾添加 20
    v.push_back(30);   // 在末尾添加 30
    v.push_back(40);   // 在末尾添加 40

    cout << "添加后:";
    for (int i = 0; i < v.size(); i++) {
        cout << v[i] << " ";
    }
    cout << endl;

    // 访问元素
    cout << "第一个元素:" << v.front() << endl;  // 10
    cout << "最后一个元素:" << v.back() << endl;  // 40
    cout << "下标为2的元素:" << v[2] << endl;     // 30

    // 修改元素
    v[1] = 99;

    // 删除最后一个元素
    v.pop_back();

    // 获取大小
    cout << "当前大小:" << v.size() << endl;  // 3

    // 判断是否为空
    cout << "是否为空:" << v.empty() << endl;  // 0 (false)

    // 清空所有元素
    v.clear();
    cout << "清空后大小:" << v.size() << endl;  // 0

    return 0;
}

3. vector 的常用方法一览

方法功能示例
push_back(x)在末尾添加元素v.push_back(10)
pop_back()删除末尾元素v.pop_back()
size()返回元素个数int n = v.size()
empty()判断是否为空if (v.empty())
clear()清空所有元素v.clear()
front()返回第一个元素int a = v.front()
back()返回最后一个元素int b = v.back()
at(i)安全访问(会检查越界)v.at(3)
insert(pos, x)在指定位置插入v.insert(v.begin()+2, 5)
erase(pos)删除指定位置的元素v.erase(v.begin()+1)

TIP

v[i] 访问时不会检查下标是否越界。如果下标超出范围,可能读到垃圾值或导致程序崩溃。如果希望安全访问,用 v.at(i)——它在越界时会抛出异常。

4. vector 的遍历方式

cpp
#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v = {10, 20, 30, 40, 50};

    // 方式1:下标遍历(最熟悉的方式)
    cout << "方式1:";
    for (int i = 0; i < v.size(); i++) {
        cout << v[i] << " ";
    }
    cout << endl;

    // 方式2:范围 for 循环(C++11 起,最推荐)
    cout << "方式2:";
    for (int x : v) {
        cout << x << " ";
    }
    cout << endl;

    // 方式3:迭代器遍历
    cout << "方式3:";
    for (auto it = v.begin(); it != v.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;

    return 0;
}

三、string —— 字符串 🔤

还记得 C 风格的字符串吗?——char 数组、\0 结尾、不能直接赋值、操作麻烦……

C++ 的 string 把这些烦恼全部解决了!

cpp
#include <iostream>
#include <string>  // 使用 string 需要包含这个头文件
using namespace std;

int main() {
    // 创建字符串
    string s1 = "Hello";
    string s2("World");
    string s3;  // 空字符串

    // 直接赋值(C 风格字符串做不到!)
    s1 = "C++ is awesome!";

    // 拼接
    string s = "Hello" + " " + "C++";
    cout << s << endl;  // Hello C++

    // 获取长度
    cout << "长度:" << s.length() << endl;  // 9
    cout << "长度:" << s.size() << endl;    // 9(和 length 一样)

    // 访问字符
    cout << "第一个字符:" << s[0] << endl;    // H
    cout << "最后一个字符:" << s.back() << endl; // +

    // 比较(直接用 == 和 !=,超方便)
    if (s1 == s2) {
        cout << "相等" << endl;
    } else {
        cout << "不相等" << endl;
    }

    // 输入
    string name;
    cout << "请输入你的名字:";
    getline(cin, name);  // 可以输入带空格的整行文本
    cout << "你好," << name << "!" << endl;

    return 0;
}

string 的常用方法

方法功能示例
length() / size()返回字符串长度s.length()
empty()判断是否为空if (s.empty())
s[i]访问第 i 个字符char c = s[0]
+拼接字符串s = s1 + s2
==, !=, <, >比较字符串if (s1 == s2)
find(sub)查找子串位置int pos = s.find("lo")
substr(pos, len)提取子串string sub = s.substr(1, 3)
insert(pos, str)插入字符串s.insert(3, "xx")
erase(pos, len)删除子串s.erase(1, 2)
getline(cin, s)读取整行(含空格)getline(cin, s)

示例:字符串查找和提取

cpp
#include <iostream>
#include <string>
using namespace std;

int main() {
    string s = "My name is Alice. I love C++.";
    
    // 查找
    size_t pos = s.find("Alice");
    if (pos != string::npos) {
        cout << "找到了,位置在:" << pos << endl;  // 11
        
        // 提取子串
        string name = s.substr(pos, 5);
        cout << "提取的名字:" << name << endl;    // Alice
    }

    // 替换
    s.replace(pos, 5, "Bob");
    cout << "替换后:" << s << endl;  // My name is Bob...

    return 0;
}

四、sort —— 排序函数 📊

之前我们手动实现了冒泡排序、选择排序、插入排序。但其实 C++ 标准库自带了一个超级好用的排序函数——sort()

cpp
#include <iostream>
#include <algorithm>  // sort 需要这个头文件
#include <vector>
using namespace std;

int main() {
    // 对普通数组排序
    int arr[] = {64, 25, 12, 22, 11};
    int n = sizeof(arr) / sizeof(arr[0]);

    sort(arr, arr + n);  // 默认升序排序

    cout << "数组升序:";
    for (int i = 0; i < n; i++) cout << arr[i] << " ";
    cout << endl;

    // 对 vector 排序
    vector<int> v = {5, 3, 8, 1, 9, 2};
    sort(v.begin(), v.end());  // 升序

    cout << "vector升序:";
    for (int x : v) cout << x << " ";
    cout << endl;

    // 降序排序
    sort(v.begin(), v.end(), greater<int>());  // 降序

    cout << "vector降序:";
    for (int x : v) cout << x << " ";
    cout << endl;

    return 0;
}

输出:

数组升序:11 12 22 25 64
vector升序:1 2 3 5 8 9
vector降序:9 8 5 3 2 1

TIP

sort() 内部使用的是 快速排序 + 插入排序 + 堆排序 的混合算法(IntroSort),时间复杂度平均 O(n log n),比我们自己手写的冒泡排序(O(n²))快得多!

所以实际开发中:优先用 sort(),只有在学习算法原理时才自己实现排序。

五、更多 STL 容器一览 🗂️

容器头文件特点适用场景
vector<vector>动态数组,支持随机访问最常用的容器,替代普通数组
string<string>字符串,支持各种操作代替 C 风格字符串
list<list>双向链表,快速插入删除频繁在中间插入/删除数据
stack<stack>栈,后进先出(LIFO)括号匹配、函数调用栈
queue<queue>队列,先进先出(FIFO)排队系统、BFS 算法
map<map>键值对,自动排序字典、成绩查询、计数
set<set>集合,元素不重复且有序去重、快速查找是否存在

NOTE

这些容器在后续的 L3 和算法学习中会逐步接触到。现阶段,先把 vectorstringsort 这三个用熟练就足够了!

六、综合示例 💻

cpp
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main() {
    // 学生成绩管理系统(STL 版本)
    vector<string> names;
    vector<int> scores;

    int n;
    cout << "请输入学生人数:";
    cin >> n;

    // 输入学生信息
    for (int i = 0; i < n; i++) {
        string name;
        int score;
        cout << "请输入第 " << i + 1 << " 个学生的姓名和成绩:";
        cin >> name >> score;
        names.push_back(name);
        scores.push_back(score);
    }

    // 输出原始数据
    cout << "\n=== 学生成绩 ===" << endl;
    for (int i = 0; i < n; i++) {
        cout << names[i] << "\t" << scores[i] << endl;
    }

    // 按成绩排序(使用 sort)
    // 提示:这里我们对成绩排序,但需要同时保持姓名对应
    // 更完整的做法是使用结构体,这里为了演示简单
    sort(scores.begin(), scores.end());

    cout << "\n=== 成绩排名(升序)===" << endl;
    for (int i = 0; i < n; i++) {
        cout << "第 " << i + 1 << " 名:" << scores[i] << endl;
    }

    // 计算平均分
    int sum = 0;
    for (int s : scores) {
        sum += s;
    }
    double avg = (double)sum / n;
    cout << "\n平均分:" << avg << endl;

    return 0;
}

七、小结 🎯

  • STL 是 C++ 的标准工具箱,包含容器、算法和迭代器。
  • vector:动态数组,自动管理内存,最常用的容器。
  • string:C++ 字符串,支持拼接、查找、截取等操作。
  • sort():高效排序函数,O(n log n),比手写排序快。
  • 学会使用 STL 可以大幅提高编程效率和代码质量

八、练习 📝

  1. vector 基本操作:创建一个 vector<int>,输入 10 个整数,然后输出它们的和与平均值。

  2. 去重:输入 n 个整数,用 vector 存储,用 sort 排序,然后输出去重后的结果(提示:相邻元素比较)。

  3. 字符串反转:输入一个字符串,用 string 存储,将其反转后输出。(提示:可以用 reverse(s.begin(), s.end())

  4. 统计字母出现次数:输入一行英文文本,统计每个字母(忽略大小写)出现的次数,输出出现次数最多的字母及其次数。

  5. 成绩排名(结构体版):定义一个 struct Student { string name; int score; },使用 vector<Student> 存储学生信息,用 sort 按成绩从高到低排序并输出。

  6. 回文判断:输入一个字符串,判断它是否为回文(正着读和反着读一样)。例如 "abcba" 是回文,"hello" 不是。

  7. 挑战题:合并两个有序数组:给定两个已排序的 vector<int>,将它们合并为一个有序的 vector<int>,不使用 sort 函数(提示:双指针法)。

💬 与我联系 QQ:774165314 | 微信:ArinRiver