C++标准库中vector和map是核心容器,vector提供连续存储的动态数组,支持高效随机访问和自动扩容,适合频繁遍历和元素数量不确定的场景;map基于红黑树实现,提供自动按键排序的键值对存储,查找、插入、删除操作时间复杂度为O(log n),适用于需要有序数据结构的场景。两者分别在性能和有序性上具有优势,是C++数据管理的基础工具。

C++标准库中的
vector
map
vector
map
std::vector
std::map
在我看来,C++标准库的容器设计得非常精妙,尤其是
vector
map
vector
map
std::vector
立即学习“C++免费学习笔记(深入)”;
std::vector
vector
#include <vector>
#include <string>
#include <iostream>
#include <map> // 即使是vector的例子,也可能需要其他头文件
int main() {
// 声明一个存储整数的vector
std::vector<int> numbers;
// 添加元素到vector的末尾
numbers.push_back(10);
numbers.push_back(20);
numbers.push_back(30);
numbers.push_back(40);
// 访问元素
std::cout << "第一个元素: " << numbers[0] << std::endl; // 可能会越界,不检查边界
std::cout << "第二个元素 (安全访问): " << numbers.at(1) << std::endl; // at()会进行边界检查,越界抛出异常
// 遍历vector
std::cout << "所有元素 (范围for循环): ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// 使用迭代器遍历
std::cout << "所有元素 (迭代器): ";
for (std::vector<int>::iterator it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 获取vector大小和容量
std::cout << "Vector大小: " << numbers.size() << std::endl;
std::cout << "Vector容量: " << numbers.capacity() << std::endl; // 容量通常 >= 大小
// 插入元素到指定位置 (效率较低,因为可能需要移动后续所有元素)
numbers.insert(numbers.begin() + 2, 25); // 在索引2处插入25
std::cout << "插入25后的Vector: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// 删除元素 (同样效率较低)
numbers.erase(numbers.begin() + 0); // 删除第一个元素
std::cout << "删除第一个元素后的Vector: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// 清空vector
numbers.clear();
std::cout << "清空后Vector大小: " << numbers.size() << std::endl;
// 预留空间,避免频繁重新分配
std::vector<std::string> names;
names.reserve(100); // 预留100个string的空间
for (int i = 0; i < 50; ++i) {
names.push_back("Name_" + std::to_string(i));
}
std::cout << "预留空间后Vector容量: " << names.capacity() << std::endl;
return 0;
}std::map
std::map
map
#include <map>
#include <string>
#include <iostream>
// vector的例子已经包含了iostream和string
// main函数可以拆分或合并,这里为了演示方便,放在同一个main函数里
// 实际使用中,通常会封装在不同的函数或类中
// int main() { // 如果是单独的map例子,可以这样开始
// 声明一个存储string键和int值的map
std::map<std::string, int> ages;
// 插入元素
ages["Alice"] = 30; // 如果键不存在,则插入;如果存在,则更新值
ages["Bob"] = 25;
ages.insert({"Charlie", 35}); // 另一种插入方式
ages.insert(std::make_pair("David", 28)); // 也可以用std::make_pair
// 访问元素
std::cout << "Alice的年龄: " << ages["Alice"] << std::endl;
// 注意:使用[]访问一个不存在的键会默认插入一个新元素,其值会被默认初始化
// std::cout << "Eve的年龄: " << ages["Eve"] << std::endl; // 此时map中会多一个键为"Eve",值为0的元素
// 安全访问元素,检查键是否存在
auto it_bob = ages.find("Bob");
if (it_bob != ages.end()) {
std::cout << "Bob的年龄 (find): " << it_bob->second << std::endl;
} else {
std::cout << "Bob不存在于map中。" << std::endl;
}
auto it_frank = ages.find("Frank");
if (it_frank != ages.end()) {
std::cout << "Frank的年龄 (find): " << it_frank->second << std::endl;
} else {
std::cout << "Frank不存在于map中。" << std::endl;
}
// 遍历map (按键的升序)
std::cout << "Map中的所有元素: " << std::endl;
for (const auto& pair : ages) { // 推荐使用const auto&
std::cout << " 键: " << pair.first << ", 值: " << pair.second << std::endl;
}
// 删除元素
ages.erase("Bob");
std::cout << "删除Bob后Map中的所有元素: " << std::endl;
for (const auto& pair : ages) {
std::cout << " 键: " << pair.first << ", 值: " << pair.second << std::endl;
}
// 获取map大小
std::cout << "Map大小: " << ages.size() << std::endl;
return 0;
// } // 如果是单独的map例子,这里结束std::vector
在我多年的C++开发经验里,
std::vector
首先,
vector
vector
vector
std::list
其次,
vector
vector
[]
at()
再者,
vector
new
delete
push_back
vector
vector
push_back
当然,
vector
vector
// 更多vector操作示例
#include <vector>
#include <iostream>
#include <algorithm> // 用于std::sort
struct MyObject {
int id;
std::string name;
MyObject(int i, const std::string& n) : id(i), name(n) {
// std::cout << "MyObject(" << id << ") 构造" << std::endl;
}
MyObject(const MyObject& other) : id(other.id), name(other.name) {
// std::cout << "MyObject(" << id << ") 拷贝构造" << std::endl;
}
MyObject(MyObject&& other) noexcept : id(other.id), name(std::move(other.name)) {
// std::cout << "MyObject(" << id << ") 移动构造" << std::endl;
}
MyObject& operator=(const MyObject& other) {
if (this != &other) {
id = other.id;
name = other.name;
// std::cout << "MyObject(" << id << ") 拷贝赋值" << std::endl;
}
return *this;
}
MyObject& operator=(MyObject&& other) noexcept {
if (this != &other) {
id = other.id;
name = std::move(other.name);
// std::cout << "MyObject(" << id << ") 移动赋值" << std::endl;
}
return *this;
}
~MyObject() {
// std::cout << "MyObject(" << id << ") 析构" << std::endl;
}
void print() const {
std::cout << "{ID: " << id << ", Name: " << name << "} ";
}
};
void print_vector_objects(const std::vector<MyObject>& vec) {
for (const auto& obj : vec) {
obj.print();
}
std::cout << std::endl;
}
// int main() { // 假设在之前的main函数之后继续
std::vector<MyObject> objects;
objects.reserve(5); // 预留空间,避免频繁重新分配
std::cout << "--- Emplace_back vs Push_back ---" << std::endl;
// emplace_back 直接在vector内部构造对象,避免一次拷贝或移动
objects.emplace_back(1, "Alpha"); // 直接构造
objects.push_back(MyObject(2, "Beta")); // 构造临时对象,然后移动到vector中 (C++11后通常是移动)
objects.emplace_back(3, "Gamma");
print_vector_objects(objects);
std::cout << "\n--- 调整大小 (resize) ---" << std::endl;
objects.resize(5, MyObject(0, "Default")); // 调整大小到5,新元素用默认值填充
print_vector_objects(objects);
objects.resize(2); // 缩小大小,多余的元素被析构
print_vector_objects(objects);
std::cout << "\n--- 排序 ---" << std::endl;
objects.emplace_back(5, "Epsilon");
objects.emplace_back(4, "Delta");
std::sort(objects.begin(), objects.end(), [](const MyObject& a, const MyObject& b) {
return a.id < b.id;
});
print_vector_objects(objects);
std::cout << "\n--- 迭代器失效示例 ---" << std::endl;
std::vector<int> nums = {1, 2, 3, 4, 5};
auto it = nums.begin() + 2; // 指向3
std::cout << "原始Vector: ";
for(int n : nums) std::cout << n << " ";
std::cout << std::endl;
// 插入操作可能导致迭代器失效
nums.insert(nums.begin(), 0); // 在开头插入,所有迭代器都可能失效
// std::cout << "失效的迭代器指向: " << *it << std::endl; // 此时it可能指向错误位置或野指针
// 正确的做法是重新获取迭代器
it = nums.begin() + 3; // 重新指向新的3 (原先的2)
std::cout << "插入后Vector: ";
for(int n : nums) std::cout << n << " ";
std::cout << std::endl;
std::cout << "重新获取的迭代器指向: " << *it << std::endl;
// 清空并释放内存
std::cout << "\n--- 清空并释放内存 (shrink_to_fit) ---" << std::endl;
std::vector<int> big_vec;
big_vec.reserve(100);
for(int i = 0; i < 10; ++i) big_vec.push_back(i);
std::cout << "初始容量: " << big_vec.capacity() << std::endl;
big_vec.clear();
std::cout << "清空后容量: " << big_vec.capacity() << std::endl; // 容量通常不变
big_vec.shrink_to_fit(); // 请求将容量缩小到与大小匹配
std::cout << "shrink_to_fit后容量: " << big_vec.capacity() << std::endl; // 容量现在可能为0
// return 0; // 如果是单独的main函数
// }std::map
std::unordered_map
这是个很经典的问题,也是我在设计系统时经常需要权衡的。
std::map
std::unordered_map
std::map
std::map
map
优点:
map
map
map
operator<
缺点:
unordered_map
unordered_map
std::unordered_map
std::unordered_map
优点:
unordered_map
map
缺点:
unordered_map
std::hash
如何选择?
我的经验是,选择哪个容器,主要看你的核心需求:
std::map
std::unordered_map
std::unordered_map
std::map
operator<
通常情况下,如果对性能没有特别严苛的要求,并且数据量不是天文数字,
std::map
std::unordered_map
// std::map 和 std::unordered_map 示例
#include <map>
#include <unordered_map>
#include <string>
#include <iostream>
struct Person {
int id;
std::string name;
// 对于std::map,需要定义 operator<
bool operator<(const Person& other) const {
return id < other.id;
}
// 对于std::unordered_map,需要定义 operator==
bool operator==(const Person& other) const {
return id == other.id;
}
};
// 为std::unordered_map 定义 Person 的哈希函数
namespace std {
template <>
struct以上就是C++标准库容器 vector map使用示例的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号