1. 底层实现
std::vector
是C++标准库中的一个模版类,用于动态数组。它的底层实现可以理解为一个动态分配的连续内存块,当需要更多空间时,内存会自动扩展。
- 内存分配:
vector
使用一块连续的内存存储元素。当插入新元素导致容量不足时,vector
会分配一块更大的内存(通常是当前容量的两倍),然后将现有元素复制过去,并释放旧的内存。 - 动态调整:为了高效增加容量,
vector
使用一个称为“几何增长”的策略,即每次扩容会增加当前容量的倍数,而非线性增加。这使得插入操作的摊销时间复杂度为 O(1)。
2. 缺点和比较
在讨论vector
的缺点时,可以和其他类似的容器(如std::deque
、std::list
)对比:
std::vector
- 缺点:
- 内存需要连续,因此在大容量时,可能难以找到足够的一块连续内存,导致内存分配失败。
- 插入和删除操作在非尾部位置有较高的开销,需要移动所有后续元素,时间复杂度为 O(n)。
- 对比:
std::deque
允许在两端快速插入/删除,没有连续内存的限制;std::list
是双向链表,可以在任意位置快速插入/删除,但不支持随机访问。
- 缺点:
3. 优点和使用场景
-
优点:
- 支持随机访问(访问任何元素的时间复杂度为 O(1)),适合需要频繁访问元素的场景。
- 自动管理内存,支持动态增长,且摊销的插入时间复杂度为 O(1)。
- 提供了一整套的STL算法支持,使用非常方便。
-
使用场景:
- 适合需要频繁访问和遍历元素的场景,比如实现一个数组、栈等。
- 适用于元素插入和删除主要发生在容器末尾的情况,因为在末尾进行操作的复杂度是 O(1)。
4. 补充和代码示例
以下是关于 std::vector
的一些常见操作示例:
#include <iostream>
#include <vector>
int main() {
// 定义一个 vector 并初始化
std::vector<int> vec = {1, 2, 3, 4, 5};
// 向 vector 尾部添加元素
vec.push_back(6);
// 插入元素
vec.insert(vec.begin() + 2, 10); // 在第三个位置插入 10
// 删除元素
vec.erase(vec.begin() + 1); // 删除第二个位置的元素
// 访问元素
for (size_t i = 0; i < vec.size(); ++i) {
std::cout << "Element at index " << i << ": " << vec[i] << std::endl;
}
// 使用迭代器访问元素
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << "Element: " << *it << std::endl;
}
// 当前容量和大小
std::cout << "Size: " << vec.size() << ", Capacity: " << vec.capacity() << std::endl;
// 缩减内存
vec.shrink_to_fit();
std::cout << "Size after shrink: " << vec.size() << ", Capacity after shrink: " << vec.capacity() << std::endl;
return 0;
}
总结
- 底层:
std::vector
是一个动态数组,内存由动态分配的连续内存块管理。 - 缺点:
- 内存必须连续,可能导致大容量时内存分配失败。
- 中间插入/删除操作开销较大。
- 优点:
- 支持随机访问。
- 动态增长,摊销插入时间复杂度为 O(1)。
- 使用场景:
- 适合频繁访问和遍历,以及主要在末尾进行插入/删除操作的场景。