【C++】零基础入门 · 第 12 节:模板与 STL 入门

到目前为止,我们已经学会了变量、函数、类、指针、文件操作等核心知识。这一节,我们来解锁 C++ 中两个超级实用的特性:模板(Template)STL(标准模板库)。它们能让你的代码更简洁、更通用、更强大!

1. 为什么需要模板?

想象一下:你写了一个函数用来求两个数的最大值。

cpp 复制代码
int maxVal(int a, int b) {
    return (a > b) ? a : b;
}

很好用!但如果我想求两个 double 的最大值呢?两个 char 的最大值呢?你可能会说:再写几个重载函数呗。

cpp 复制代码
double maxVal(double a, double b) {
    return (a > b) ? a : b;
}

可是这样每多一种类型,就要多写一个函数,太麻烦了。模板就是用来解决这个问题的------你只需要写一次,编译器会自动帮你生成适用于各种类型的版本。

2. 函数模板

2.1 基本语法

函数模板的写法非常简单,在函数前面加上 template <typename T> 就行:

cpp 复制代码
#include <iostream>
using namespace std;

template <typename T>
T maxVal(T a, T b) {
    return (a > b) ? a : b;
}

int main() {
    cout << "int: " << maxVal(3, 7) << endl;
    cout << "double: " << maxVal(3.14, 2.71) << endl;
    cout << "char: " << maxVal('a', 'z') << endl;
    return 0;
}

输出:

复制代码
int: 7
double: 3.14
char: z

这里的 T 就是一个 类型占位符 。当你调用 maxVal(3, 7) 时,编译器发现参数是 int,就把 T 替换成 int;调用 maxVal(3.14, 2.71) 时,T 就变成 double

你可以把 T 想象成一个"待填写的类型空格",编译器会根据你的调用自动填上正确的类型。

2.2 多个模板参数

模板参数也可以有多个:

cpp 复制代码
#include <iostream>
using namespace std;

template <typename T1, typename T2>
void printPair(T1 a, T2 b) {
    cout << "(" << a << ", " << b << ")" << endl;
}

int main() {
    printPair(1, 3.14);
    printPair("hello", 42);
    printPair('A', true);
    return 0;
}

输出:

复制代码
(1, 3.14)
(hello, 42)
(A, 1)

3. 类模板

函数可以模板化,类当然也可以!

3.1 一个简单的 Pair 类模板

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

template <typename T1, typename T2>
class Pair {
public:
    T1 first;
    T2 second;

    Pair(T1 a, T2 b) : first(a), second(b) {}

    void print() const {
        cout << "(" << first << ", " << second << ")" << endl;
    }
};

int main() {
    Pair<int, double> p1(1, 3.14);
    Pair<string, int> p2("年龄", 18);

    p1.print();
    p2.print();
    return 0;
}

输出:

复制代码
(1, 3.14)
(年龄, 18)

注意使用类模板时,需要在尖括号里 显式指定类型 ,比如 Pair<int, double>。这和函数模板不同,函数模板通常可以自动推导类型,但类模板一般需要你手动告诉它。

3.2 一个简单的 Stack 类模板

再来一个稍微实用一点的例子------用模板实现一个简单的栈(Stack):

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

template <typename T>
class SimpleStack {
private:
    T data[100];
    int topIndex;

public:
    SimpleStack() : topIndex(-1) {}

    void push(const T& val) {
        if (topIndex >= 99) {
            cout << "栈已满!" << endl;
            return;
        }
        data[++topIndex] = val;
    }

    T pop() {
        if (topIndex < 0) {
            cout << "栈为空!" << endl;
            return T();
        }
        return data[topIndex--];
    }

    bool empty() const {
        return topIndex < 0;
    }
};

int main() {
    // 整数栈
    SimpleStack<int> intStack;
    intStack.push(10);
    intStack.push(20);
    intStack.push(30);
    cout << "弹出: " << intStack.pop() << endl;  // 30
    cout << "弹出: " << intStack.pop() << endl;  // 20

    // 字符串栈
    SimpleStack<string> strStack;
    strStack.push("你好");
    strStack.push("世界");
    cout << "弹出: " << strStack.pop() << endl;  // 世界
    cout << "弹出: " << strStack.pop() << endl;  // 你好

    return 0;
}

输出:

复制代码
弹出: 30
弹出: 20
弹出: 世界
弹出: 你好

同一个 SimpleStack 类,通过模板就能存放不同类型的数据,这就是模板的威力!

4. 什么是 STL?

STL(Standard Template Library,标准模板库) 是 C++ 自带的一个"工具箱",里面包含了大量常用的数据结构和算法。你可以把它想象成一个超级工具箱 :需要收纳就用 vector,需要查字典就用 map,需要排序就用 sort------都不用自己从零造轮子。

STL 主要由三部分组成:

  • 容器(Container) :用来存放数据,比如 vectormapset
  • 算法(Algorithm) :用来处理数据,比如 sortfind
  • 迭代器(Iterator):连接容器和算法的"桥梁"

5. STL 容器:vector

vector 是 STL 中最常用的容器,可以理解为一个自动扩容的数组

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;

int main() {
    // 创建一个空的 vector
    vector<int> nums;

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

    // 用下标访问
    cout << "第一个元素: " << nums[0] << endl;

    // 获取大小
    cout << "大小: " << nums.size() << endl;

    // 遍历(范围 for 循环)
    cout << "所有元素: ";
    for (int n : nums) {
        cout << n << " ";
    }
    cout << endl;

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

    cout << "删除后大小: " << nums.size() << endl;

    return 0;
}

输出:

复制代码
第一个元素: 10
大小: 4
所有元素: 10 20 30 40
删除后大小: 3

和普通数组相比,vector 的好处是:你不需要提前知道要存多少数据,它可以自动增长。push_back 加一个,pop_back 删一个,size() 问大小------非常方便。

6. STL 容器:map

map 就像一本字典 ,它存储的是 键值对(key-value pair):你给它一个"键",它返回对应的"值"。

cpp 复制代码
#include <iostream>
#include <map>
#include <string>
using namespace std;

int main() {
    map<string, int> ages;

    // 添加键值对
    ages["小明"] = 18;
    ages["小红"] = 20;
    ages["小刚"] = 19;

    // 通过键访问值
    cout << "小明的年龄: " << ages["小明"] << endl;

    // 查找键是否存在
    if (ages.find("小红") != ages.end()) {
        cout << "小红存在,年龄: " << ages["小红"] << endl;
    }

    // 遍历 map
    for (const auto& pair : ages) {
        cout << pair.first << " -> " << pair.second << endl;
    }

    return 0;
}

输出:

复制代码
小明的年龄: 18
小红存在,年龄: 20
小刚 -> 19
小明 -> 18
小红 -> 20

map 内部会自动按键排序(这里按字符串的字典序),查找速度也很快。适合需要"通过名字找数据"的场景。

7. STL 容器:set

set 是一个自动去重的有序集合。你往里面丢元素,它会自动帮你排好序并且去掉重复的。

cpp 复制代码
#include <iostream>
#include <set>
using namespace std;

int main() {
    set<int> s;

    s.insert(30);
    s.insert(10);
    s.insert(20);
    s.insert(10);  // 重复,不会插入
    s.insert(30);  // 重复,不会插入

    cout << "大小: " << s.size() << endl;  // 3

    cout << "元素: ";
    for (int n : s) {
        cout << n << " ";
    }
    cout << endl;

    // 查找
    if (s.count(20)) {
        cout << "20 存在" << endl;
    }

    return 0;
}

输出:

复制代码
大小: 3
元素: 10 20 30
20 存在

set 非常适合需要"不重复"和"自动排序"的场景,比如记录一组不重复的学号。

8. STL 算法:sort 和 find

STL 提供了很多现成的算法函数,配合容器和迭代器使用,功能强大。

8.1 sort 排序

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> nums = {5, 2, 8, 1, 9, 3};

    // 升序排序
    sort(nums.begin(), nums.end());

    cout << "升序: ";
    for (int n : nums) {
        cout << n << " ";
    }
    cout << endl;

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

    cout << "降序: ";
    for (int n : nums) {
        cout << n << " ";
    }
    cout << endl;

    return 0;
}

输出:

复制代码
升序: 1 2 3 5 8 9
降序: 9 8 5 3 2 1

sort 接收两个迭代器参数,表示要排序的范围:begin() 指向第一个元素,end() 指向最后一个元素的后面。greater<int>() 表示用"大于"来比较,从而实现降序。

8.2 find 查找

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

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

    auto it = find(nums.begin(), nums.end(), 30);

    if (it != nums.end()) {
        cout << "找到了!下标是: " << it - nums.begin() << endl;
    } else {
        cout << "没找到" << endl;
    }

    return 0;
}

输出:

复制代码
找到了!下标是: 2

find 返回一个迭代器,如果找到了就指向那个元素,没找到就返回 end()

9. 为什么 STL 值得学?

STL 的好处可以用一句话概括:别人帮你写好了,你直接用就行

  • 高效:STL 的实现经过了大量优化,性能比你自己写的代码通常更好
  • 可靠:经过了几十年的测试和验证,Bug 极少
  • 通用 :学会了 vectormapsort,你就能解决大部分编程问题
  • 面试必问:STL 是 C++ 面试中的高频考点

10. 总结

这一节我们学习了 C++ 中两个非常重要的特性:

  • 模板 让我们写出与类型无关的通用代码。函数模板用 template <typename T> 声明,编译器会自动推导类型;类模板需要在使用时显式指定类型。
  • STL 是 C++ 内置的工具箱,包含容器、算法和迭代器三大组件。vector 是自动扩容的数组,map 是键值对字典,set 是有序不重复集合,sortfind 是最常用的算法。

模板和 STL 是 C++ 的精髓所在。掌握了它们,你就迈入了"用 C++ 高效编程"的大门。下一节,我们将继续深入探索更多 STL 容器和算法。加油!

相关推荐
天月风沙1 小时前
基于机器视觉的实验室器件仓储系统设计——内蒙古自治区国家级大创工程存档
开发语言·python
24zhgjx-fuhao1 小时前
虚链路的配置
开发语言·网络·php
techdashen2 小时前
Rust 中的小字符串:smol_str 与 smartstring 的对决
开发语言·后端·rust
wanghu20242 小时前
ABC460_E题题解
c++·算法
devilnumber2 小时前
java自定义事件处理器极简版:「外卖点餐」场景
java·开发语言
小何code2 小时前
C语言【初阶】第1节,初识C语言
c语言·开发语言
代码小书生2 小时前
getpass,一个安全输入的 Python 库!
开发语言·python·安全
莫陌尛.2 小时前
Fuzzy C-Mean Clustering (FCM)
c语言·开发语言
YOU OU2 小时前
案例综合练习-博客系统
java·开发语言