(C++)标准模板库(STL)相关介绍(C++教程)
C++ 中类似 string 的重要知识点(STL 容器详解)
在 C++ 中,类似 string
的容器类都是标准模板库(STL)的一部分,它们提供了更高级的数据抽象和更安全的内存管理。以下是几个最常用的 STL 容器,我将逐一详细介绍:
1. vector(动态数组)
基本特性
-
作用:替代 C 语言中的数组,提供动态大小调整
-
头文件:
#include <vector>
-
内存管理:自动处理内存分配和释放
基本用法
#include <iostream>
#include <vector>
using namespace std;int main() {// 创建 vectorvector<int> numbers;// 添加元素numbers.push_back(10);numbers.push_back(20);numbers.push_back(30);// 访问元素cout << "第一个元素: " << numbers[0] << endl; // 10cout << "最后一个元素: " << numbers.back() << endl; // 30// 遍历元素cout << "所有元素: ";for (int num : numbers) {cout << num << " ";}// 输出: 10 20 30// 删除元素numbers.pop_back(); // 删除最后一个元素// 大小操作cout << "\n当前大小: " << numbers.size() << endl; // 2numbers.resize(5); // 调整大小为5cout << "调整后大小: " << numbers.size() << endl; // 5return 0;
}
与 C 数组对比
特性 | C 数组 | vector |
---|---|---|
大小固定 | 是 | 否(动态调整) |
内存管理 | 手动 | 自动 |
越界检查 | 无 | 有(使用 at()) |
功能扩展 | 无 | 丰富的方法 |
实际应用场景
-
存储动态数量的数据(如用户输入)
-
需要频繁在尾部添加/删除元素的场景
-
需要随机访问元素的集合
2. map(关联容器)
基本特性
-
作用:键值对存储,类似 Python 的字典
-
头文件:
#include <map>
-
特性:按键自动排序(基于红黑树)
基本用法
#include <iostream>
#include <map>
#include <string>
using namespace std;int main() {// 创建 mapmap<string, int> studentScores;// 添加键值对studentScores["Alice"] = 95;studentScores["Bob"] = 87;studentScores["Charlie"] = 92;// 访问元素cout << "Alice 的分数: " << studentScores["Alice"] << endl;// 遍历元素cout << "所有学生分数:\n";for (const auto& pair : studentScores) {cout << pair.first << ": " << pair.second << endl;}// 查找元素if (studentScores.find("David") == studentScores.end()) {cout << "David 不在记录中" << endl;}// 删除元素studentScores.erase("Bob");return 0;
}
与 C 结构体数组对比
特性 | C 结构体数组 | map |
---|---|---|
查找效率 | O(n) | O(log n) |
自动排序 | 否 | 是 |
键唯一性 | 手动保证 | 自动保证 |
动态扩展 | 复杂 | 简单 |
实际应用场景
-
字典/词典实现
-
配置参数存储
-
缓存系统实现
-
需要按键快速查找的场景
3. list(双向链表)
基本特性
-
作用:高效的插入和删除操作
-
头文件:
#include <list>
-
特性:双向链表结构,不支持随机访问
基本用法
#include <iostream>
#include <list>
using namespace std;int main() {list<int> numbers = {10, 20, 30};// 在开头添加元素numbers.push_front(5);// 在末尾添加元素numbers.push_back(40);// 在中间插入元素auto it = numbers.begin();advance(it, 2); // 移动到第三个位置numbers.insert(it, 25);// 遍历元素cout << "链表内容: ";for (int num : numbers) {cout << num << " "; // 5 10 25 20 30 40}// 删除元素numbers.remove(20); // 删除所有值为20的元素// 排序numbers.sort();return 0;
}
与 C 链表对比
特性 | C 链表 | list |
---|---|---|
内存管理 | 手动 | 自动 |
类型安全 | 弱 | 强 |
内置算法 | 无 | 丰富(sort, merge等) |
迭代器支持 | 手动 | 强大 |
实际应用场景
-
需要频繁在任意位置插入/删除元素的场景
-
实现队列和栈
-
需要稳定排序的情况
4. set(集合)
基本特性
-
作用:存储唯一元素,自动排序
-
头文件:
#include <set>
-
特性:元素自动排序且唯一
基本用法
#include <iostream>
#include <set>
using namespace std;int main() {set<int> uniqueNumbers;// 添加元素uniqueNumbers.insert(30);uniqueNumbers.insert(10);uniqueNumbers.insert(20);uniqueNumbers.insert(10); // 重复元素不会被添加// 遍历元素cout << "集合内容: ";for (int num : uniqueNumbers) {cout << num << " "; // 10 20 30}// 检查存在性if (uniqueNumbers.find(20) != uniqueNumbers.end()) {cout << "\n20 在集合中";}// 删除元素uniqueNumbers.erase(10);return 0;
}
实际应用场景
-
去重操作
-
数学集合运算(并集、交集等)
-
需要自动排序的独特元素集合
5. stack 和 queue(适配器容器)
基本特性
-
作用:提供特定数据结构接口
-
头文件:
#include <stack>
或#include <queue>
-
底层实现:基于 deque 或 list
stack 用法
#include <iostream>
#include <stack>
using namespace std;int main() {stack<int> numStack;// 压栈numStack.push(10);numStack.push(20);numStack.push(30);// 访问栈顶cout << "栈顶元素: " << numStack.top() << endl; // 30// 出栈numStack.pop();// 检查是否为空if (!numStack.empty()) {cout << "新栈顶: " << numStack.top() << endl; // 20}return 0;
}
queue 用法
#include <iostream>
#include <queue>
using namespace std;int main() {queue<string> nameQueue;// 入队nameQueue.push("Alice");nameQueue.push("Bob");nameQueue.push("Charlie");// 访问队首cout << "队首: " << nameQueue.front() << endl; // Alice// 出队nameQueue.pop();// 访问新队首cout << "新队首: " << nameQueue.front() << endl; // Bobreturn 0;
}
实际应用场景
-
stack:函数调用栈、表达式求值、撤销操作
-
queue:任务调度、消息队列、BFS 算法
6. pair 和 tuple(复合类型)
pair 基本用法
#include <iostream>
#include <utility> // 包含 pair
using namespace std;int main() {// 创建 pairpair<string, int> person("Alice", 30);// 访问元素cout << "姓名: " << person.first << endl;cout << "年龄: " << person.second << endl;// 创建 pair 的其他方式auto student = make_pair("Bob", 85.5);return 0;
}
tuple 基本用法
#include <iostream>
#include <tuple>
using namespace std;int main() {// 创建 tupletuple<string, int, double> employee("Charlie", 25, 75000.50);// 访问元素cout << "姓名: " << get<0>(employee) << endl;cout << "年龄: " << get<1>(employee) << endl;cout << "薪资: " << get<2>(employee) << endl;// 结构化绑定 (C++17)auto [name, age, salary] = employee;cout << name << " 的年龄是 " << age << ",薪资是 " << salary << endl;return 0;
}
通用特性(所有 STL 容器共享)
-
自动内存管理
vector<int> nums; nums.push_back(10); // 自动分配内存 // 不需要手动释放,离开作用域自动销毁
-
迭代器支持
vector<int> numbers = {1, 2, 3, 4, 5};// 使用迭代器遍历 for (auto it = numbers.begin(); it != numbers.end(); ++it) {cout << *it << " "; }
-
算法支持
#include <algorithm>vector<int> nums = {5, 3, 1, 4, 2};// 排序 sort(nums.begin(), nums.end());// 查找 auto pos = find(nums.begin(), nums.end(), 3); if (pos != nums.end()) {cout << "找到3,位置: " << distance(nums.begin(), pos); }
-
类型安全
vector<string> names; names.push_back("Alice"); // names.push_back(123); // 编译错误,类型不匹配
学习建议
-
学习路径:
-
练习项目:
-
使用 vector 实现学生成绩管理系统
-
使用 map 实现单词计数器
-
使用 stack 实现表达式计算器
-
使用 queue 实现简单消息队列
-
-
调试技巧:
-
使用范围 for 循环简化遍历
-
使用
size()
而不是 C 的sizeof
-
利用 IDE 的容器可视化工具(VS、CLion)
-
-
性能考虑:
-
小数据:vector 通常最快
-
频繁插入/删除中间:list
-
键值查找:unordered_map (哈希表) 通常最快
-
总结
C++ 的 STL 容器(vector, map, list, set 等)提供了比原始 C 数据结构更安全、更高效的替代方案。它们:
-
自动管理内存:避免内存泄漏
-
提供丰富接口:简化常见操作
-
保证类型安全:减少运行时错误
-
支持泛型编程:适用于各种数据类型
-
与算法库集成:提供强大的数据处理能力
掌握这些容器是成为高效 C++ 程序员的关键一步,它们能让你专注于问题本身而不是底层细节,大大提高开发效率和代码质量。
后续的时间我将逐个带大家了解STL库
注:该代码是本人自己所写,可能不够好,不够简便,欢迎大家指出我的不足之处。如果遇见看不懂的地方,可以在评论区打出来,进行讨论,或者联系我。上述内容全是我自己理解的,如果你有别的想法,或者认为我的理解不对,欢迎指出!!!如果可以,可以点一个免费的赞支持一下吗?谢谢各位彦祖亦菲!!!!!