✅ 本篇目标:
- 理解 函数模板 与 类模板
- 掌握 STL 算法 (
sort,find,for_each)- 学会使用 lambda 表达式
- 实战项目:通用计算器 + 学生成绩排序系统
🕒 建议学习时间:3--4 小时|可分多次完成💡 本篇将让你写出高度复用、类型安全、性能卓越的代码!
📘 C++ 零基础入门教程(第 6 篇)
模板与 STL 算法 ------ 写一次,用万次
第一步:为什么需要模板?
假设你想写一个函数,求两个数的最大值:
cpp
int max(int a, int b) { return (a > b) ? a : b; }
double max(double a, double b) { ... } // 重复!
string max(string a, string b) { ... } // 又重复!
❌ 问题:为每种类型写一遍,代码冗余,难以维护。
✅ 解决方案:函数模板(Function Template)
cpp
#include <iostream>
using namespace std;
// 模板声明
template<typename T>
T myMax(T a, T b) {
return (a > b) ? a : b;
}
int main() {
cout << myMax(3, 5) << endl; // int
cout << myMax(3.14, 2.71) << endl; // double
cout << myMax(string("Hi"), string("Hello")) << endl; // string
return 0;
}
✅ 输出:
5
3.14
Hi
🔑 关键点:
template<typename T>声明一个类型参数T- 编译器会为每种调用类型自动生成具体函数(称为"实例化")
typename也可写作class(历史原因),但推荐用typename
第二步:类模板(Class Template)
同样,我们可以让类支持任意类型。
示例:通用栈(Stack)
cpp
#include <vector>
#include <stdexcept>
using namespace std;
template<typename T>
class Stack {
private:
vector<T> data;
public:
void push(const T& item) {
data.push_back(item);
}
T pop() {
if (data.empty()) {
throw runtime_error("Stack is empty!");
}
T top = data.back();
data.pop_back();
return top; // 注意:这里可能拷贝,可用移动优化(第5篇)
}
bool empty() const {
return data.empty();
}
};
// 使用
int main() {
Stack<int> intStack;
intStack.push(10);
intStack.push(20);
cout << intStack.pop() << endl; // 20
Stack<string> strStack;
strStack.push("Hello");
strStack.push("C++");
cout << strStack.pop() << endl; // C++
return 0;
}
💡 这就是
std::stack、std::vector的工作原理!
第三步:STL 算法 ------ 不用手写循环!
STL 提供大量通用算法,配合容器使用,代码更简洁、高效、安全。
常用算法头文件:
cpp
#include <algorithm> // sort, find, transform...
#include <numeric> // accumulate
3.1 std::sort ------ 排序
cpp
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
vector<int> nums = {5, 2, 8, 1, 9};
sort(nums.begin(), nums.end()); // 升序
for (int x : nums) cout << x << " "; // 1 2 5 8 9
// 降序:传入比较函数
sort(nums.begin(), nums.end(), greater<int>());
for (int x : nums) cout << x << " "; // 9 8 5 2 1
return 0;
}
3.2 自定义排序:对学生按成绩排序
cpp
class Student {
public:
string name;
double score;
Student(string n, double s) : name(n), score(s) {}
};
// 方法1:重载 < 运算符
bool operator<(const Student& a, const Student& b) {
return a.score < b.score; // 按分数升序
}
// 方法2:用 lambda(推荐!)
int main() {
vector<Student> students = {
{"Alice", 95},
{"Bob", 88},
{"Charlie", 92}
};
// 使用 lambda 自定义排序规则
sort(students.begin(), students.end(),
[](const Student& a, const Student& b) {
return a.score > b.score; // 降序:高分在前
});
for (const auto& s : students) {
cout << s.name << ": " << s.score << endl;
}
return 0;
}
✅ 输出:
Alice: 95
Charlie: 92
Bob: 88
🔥 Lambda 表达式 :
[capture](params) { body }是一种匿名函数,特别适合传给算法!
3.3 其他常用算法
| 算法 | 用途 |
|---|---|
find(begin, end, value) |
查找元素 |
count(begin, end, value) |
统计出现次数 |
accumulate(begin, end, init) |
求和(需 <numeric>) |
transform(...) |
批量转换(如平方每个元素) |
示例:计算平均分(不用手写循环)
cpp
#include <numeric>
double total = accumulate(students.begin(), students.end(), 0.0,
[](double sum, const Student& s) {
return sum + s.score;
});
double avg = total / students.size();
第四步:实战项目 1 ------ 通用计算器(模板版)
支持任意数值类型(int, double, float)的加减乘除。
cpp
// calculator.cpp
#include <iostream>
using namespace std;
template<typename T>
class Calculator {
public:
static T add(T a, T b) { return a + b; }
static T subtract(T a, T b) { return a - b; }
static T multiply(T a, T b) { return a * b; }
static T divide(T a, T b) {
if (b == 0) throw invalid_argument("Division by zero!");
return a / b;
}
};
int main() {
cout << "整数: " << Calculator<int>::add(3, 5) << endl;
cout << "浮点: " << Calculator<double>::divide(10.0, 3.0) << endl;
return 0;
}
✅ 输出:
整数: 8
浮点: 3.33333
💡 使用
static成员函数,无需创建对象。
第五步:实战项目 2 ------ 学生成绩分析系统(STL 算法版)
功能:
- 按成绩排序(高到低)
- 找出最高分学生
- 计算平均分
- 筛选及格学生
cpp
// grade_analysis.cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;
struct Student {
string name;
double score;
};
void analyzeGrades(vector<Student>& students) {
// 1. 按分数降序排序
sort(students.begin(), students.end(),
[](const Student& a, const Student& b) {
return a.score > b.score;
});
// 2. 打印排序后列表
cout << "\n--- 排名 ---\n";
for (size_t i = 0; i < students.size(); ++i) {
cout << (i + 1) << ". " << students[i].name
<< " (" << students[i].score << ")\n";
}
// 3. 计算平均分
double total = accumulate(students.begin(), students.end(), 0.0,
[](double sum, const Student& s) {
return sum + s.score;
});
cout << "\n平均分: " << (total / students.size()) << endl;
// 4. 筛选及格学生(>=60)
vector<Student> passed;
copy_if(students.begin(), students.end(), back_inserter(passed),
[](const Student& s) { return s.score >= 60; });
cout << "\n及格人数: " << passed.size() << "/" << students.size() << endl;
}
int main() {
vector<Student> students = {
{"Alice", 95}, {"Bob", 55}, {"Charlie", 88}, {"David", 45}
};
analyzeGrades(students);
return 0;
}
✅ 输出:
--- 排名 ---
1. Alice (95)
2. Charlie (88)
3. Bob (55)
4. David (45)
平均分: 70.75
及格人数: 2/4
🎯 亮点:
copy_if+back_inserter:优雅筛选- 全程使用 STL 算法,无手动 for 循环
- 代码清晰、高效、可读性强
📌 本篇小结:你已掌握
| 概念 | 说明 |
|---|---|
| 函数模板 | template<typename T> T func(T a, T b) |
| 类模板 | template<typename T> class Container { ... }; |
| STL 算法 | sort, find, accumulate, copy_if... |
| Lambda 表达式 | [=](int x) { return x * 2; } |
| 泛型思维 | 写通用代码,适配多种类型 |
✅ 下一步建议
- 尝试 :用
transform将所有学生成绩加 5 分 - 思考 :如何对
map按 value 排序?(提示:转成 vector of pairs) - 预习:什么是"异常安全"?如何正确处理错误?