std::vector 的底层实现原理
std::vector 是 C++ 标准库提供的动态数组,具有自动管理其存储的功能。其底层实现主要通过以下几个方面来保证其功能和性能:
- 动态数组:std::vector 底层使用动态数组来存储元素。初始容量较小,当需要存储的元素超出当前容量时,vector 会自动扩容。
- 连续存储:vector 保证其元素在内存中是连续存储的,这使得随机访问非常快(时间复杂度为 O(1))。
- 管理容量和大小:vector 有两个重要的成员变量:size 和 capacity。size 表示当前存储的元素个数,而 capacity 表示当前分配的内存可以容纳的最大元素个数。
vector 的扩容机制
当向 vector 添加元素且当前容量不足时,vector 需要扩容。扩容过程如下:
- 分配新内存:vector 通常会分配比当前容量更多的内存,新容量一般是当前容量的 1.5 倍到 2 倍,以减少频繁的扩容操作。这种策略在大多数实现中都类似,但具体的扩容因子可能会有所不同。
- 移动元素:将当前元素从旧内存块复制或移动到新内存块中。对于非平凡类型的元素(即具有非平凡的复制构造函数、移动构造函数或析构函数的类型),这是一个元素逐个调用构造和析构的过程。
- 释放旧内存:完成元素搬迁后,释放旧的内存块。
举个简单的例子:
std::vector vec;
vec.push_back(1); // 初始容量可能是 1
vec.push_back(2); // 容量不足,扩容。新容量可能是 2
vec.push_back(3); // 容量再次不足,扩容。新容量可能是 4
clear 方法是否清除内存
调用 clear() 方法会清除 vector 中的所有元素,但不会释放其分配的内存。具体来说:
- 元素析构:clear() 会调用所有元素的析构函数,用于销毁当前存储的所有对象。
- size 变为 0:clear() 之后,vector 的 size 会变为 0,但 capacity 保持不变。这意味着内存仍然保留以备将来使用。
std::vector vec = {1, 2, 3, 4};
vec.clear(); // vec.size() 变为 0,但 vec.capacity() 不变
如何实现内容的清除和内存的释放
如果需要同时清除内容并释放内存,可以使用 shrink_to_fit() 或直接重新分配内存:
- shrink_to_fit:这是 C++11 引入的一个方法,用于请求释放未使用的内存。它尝试减小 vector 的容量以匹配当前的大小,但标准并不保证一定会释放所有多余的内存。
std::vector vec = {1, 2, 3, 4};
vec.clear();
vec.shrink_to_fit(); // 请求释放未使用的内存
- 重新分配内存:通过交换一个空的 vector 可以强制释放内存。
std::vector vec = {1, 2, 3, 4};
std::vector().swap(vec); // 清除内容并释放内存
总结
- std::vector 使用动态数组实现,保证元素连续存储。
- 当需要扩容时,vector 会分配更大的内存块,搬移元素,然后释放旧内存。
- clear() 方法只是清除元素,不会释放内存。
- 使用 shrink_to_fit() 或重新分配内存的方法可以实现内容清除和内存释放。