分组对象
约 569 个字 229 行代码 预计阅读时间 8 分钟
C++容器
C++标准模板库(STL)提供了多种容器类,用于存储和管理对象集合。这些容器适用于不同的使用场景,包括顺序容器(vector, list等)和关联容器(map等)。
顺序容器
-
Vector
Vector是一种动态数组,支持快速随机访问,在末尾添加和删除元素效率高。
// 基本操作 v.size(); // 获取元素数量 v.empty(); // 检查是否为空 v.begin(); // 返回首元素迭代器 v.end(); // 返回尾后迭代器 // 元素访问 v[index]; // 访问指定位置元素(无边界检查) v.at(index); // 访问指定位置元素(有边界检查) v.front(); // 访问首元素 v.back(); // 访问尾元素 // 修改 v.push_back(e); // 末尾添加元素 v.pop_back(); // 删除末尾元素 v.insert(pos, e); // 在指定位置插入元素 v.erase(pos); // 删除指定位置元素 v.clear(); // 清空所有元素
#include <iostream> #include <vector> using namespace std; int main() { // 声明整数vector vector<int> x; // 添加元素 for (int a = 0; a < 1000; a++) x.push_back(a); // 使用迭代器遍历 vector<int>::iterator p; for (p = x.begin(); p < x.end(); p++) cout << *p << " "; // 基于范围的for循环(C++11) for (auto var : x) cout << var << " "; return 0; }
-
List
List是双向链表,支持在任意位置高效插入和删除,但不支持随机访问。
// 基本操作 lst.size(); // 获取元素数量 lst.empty(); // 检查是否为空 // 元素访问 lst.front(); // 访问首元素 lst.back(); // 访问尾元素 // 修改 lst.push_back(item); // 末尾添加元素 lst.push_front(item); // 开头添加元素 lst.pop_back(); // 删除末尾元素 lst.pop_front(); // 删除开头元素 lst.insert(pos, value); // 在迭代器位置插入 lst.erase(pos); // 删除迭代器位置元素 lst.erase(pos1, pos2); // 删除范围内元素
#include <iostream> #include <list> #include <string> using namespace std; int main() { // 声明字符串list list<string> s; // 添加元素 s.push_back("hello"); s.push_back("world"); s.push_front("tide"); s.push_front("crimson"); s.push_front("alabama"); // 使用迭代器遍历 list<string>::iterator p; for (p = s.begin(); p != s.end(); p++) cout << *p << " "; cout << endl; // 删除第二个元素 list<int> L; for(int i = 1; i <= 5; ++i) L.push_back(i); L.erase(++L.begin()); // 删除第二个元素 // 注意:迭代器失效问题 list<int>::iterator li = L.begin(); L.erase(li); // li现在无效 // 正确做法:使用erase的返回值 li = L.erase(li); // li指向下一个元素 return 0; }
-
其他顺序容器
双端队列(double-ended queue),支持在两端高效插入和删除。
单向链表,比list更节省空间,但只能向前遍历。
-
容器选择指南
容器 随机访问 头部插入/删除 尾部插入/删除 中间插入/删除 vector 快 慢 快 慢 list 慢(不支持) 快 快 快 deque 快 快 快 慢 forward_list 慢(不支持) 快 慢(不支持) 快 - 需要随机访问? 选择vector或deque
- 主要在容器中间插入/删除? 选择list
- 需要在两端操作? 选择deque
- 空间效率优先? 考虑forward_list
- 需要更好的迭代器稳定性? 选择list
关联容器
-
Map
Map是关联数组,存储键值对,根据键快速查找值,键不能重复且自动排序。
#include <map> #include <string> #include <iostream> using namespace std; int main() { // 价格表 map<string, float> price; price["snapple"] = 0.75; price["coke"] = 0.50; // 计算总价 string item; double total = 0; while (cin >> item) total += price[item]; // 判断是否是完全平方数 map<long, int> root; root[4] = 2; root[1000000] = 1000; long l; cin >> l; if (root.count(l)) // 检查键是否存在 cout << root[l]; else cout << "Not perfect square"; // 使用基于范围的for循环遍历(C++11) for (auto entry : price) { cout << entry.first << ": " << entry.second << endl; } return 0; }
迭代器
迭代器是访问容器中元素的通用方式,类似于指针。
常见陷阱
- Vector越界:
v[100]=1;
如果vector大小小于101,这是未定义行为 - 使用operator[]与不存在的键:
if (foo["bob"]==1)
会默默创建键"bob" - 迭代器失效: 在修改容器后,某些迭代器可能失效
C++11新特性
- Auto关键字: 自动推导类型,简化迭代器声明
- 基于范围的for循环: 简化遍历
- 类型别名: 使用using简化复杂类型