std::vector的容量会降低吗?

Will a std::vector's capacity ever be reduced?

本文关键字:容量 vector std      更新时间:2023-10-16

>C++14 最终工作草案对std::vector做出了以下评论:

存储管理是自动处理的,但可以给出提示以提高效率。

CPP偏好 说:

载体的存储是自动处理的,根据需要进行扩展和收缩。

动态数组的维基百科条目说:

C++ 的std::vector和 Rust 的std::vec::Vec是动态数组的实现

所以我认为当一个向量的容量远大于它的大小时,它应该自动减小它的容量。我编写了以下代码来检查我的假设:

#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {};
cout << "initialization" << endl;
cout << "  capacity: " << v.capacity() << endl;
cout << "  size: " << v.size() << endl;
for (int i = 1; i <= 10000; i++) 
v.push_back(i);
cout << "after inserting a lot of elements" << endl;
cout << "  capacity: " << v.capacity() << endl;
cout << "  size: " << v.size() << endl;
v.erase(v.begin() + 1, v.begin() + 10000);
cout << "after erasing a lot of elements" << endl;
cout << "  capacity: " << v.capacity() << endl;
cout << "  size: " << v.size() << endl;
v.push_back(9);
cout << "after inserting another element" << endl;
cout << "  capacity: " << v.capacity() << endl;
cout << "  size: " << v.size() << endl;
}

我使用g++ -std=c++14 code.cc来编译代码。运行结果a.out将生成以下输出。我正在使用macOS Mojave。

initialization
capacity: 0
size: 0
after inserting a lot of elements
capacity: 16384
size: 10000
after erasing a lot of elements
capacity: 16384
size: 1
after inserting another element
capacity: 16384
size: 2

因此,似乎std::vector即使其容量远大于其大小也不会降低其容量。

std::vector会减少其容量吗?
那么,是否有一些条件可以触发其产能的减少呢?

所以我认为当一个向量的容量远大于它的大小时,它应该降低它的容量。

首先,标准必须具体说明"容量远大于其大小"的含义。这将限制实施目前对重新分配战略的选择。

其次,如果减少容量需要重新分配和移动所有剩余的元素。这意味着所有迭代器都可能因擦除而失效,从而限制了安全使用。

目前,擦除状态

使迭代器和引用在擦除点或之后失效,包括end()迭代器。

第三,一个载体再次达到其高容量水位线的可能性与它长时间保持小水位的可能性一样大。

对于许多有效方案,您将使使用情况变得更糟,因为释放大量分配的可疑好处。现代虚拟内存系统可以很好地处理旧分配,这些分配严格比必要时间更长。

那么,是否有一些条件可以触发其产能的减少呢?

是的,shrink_to_fit是做你想做的事的明确要求。如果您确实希望它重新分配给较小的大小,您可以要求这样做。其他会受到螫头伤害的用法不受影响。

如果实现中的std::vector::shrink_to_fit()没有实现您想要实现的目标(因为它只是发出一个非约束性请求来减少向量的容量(,您可以考虑在向量v上应用交换以适应习惯用法:

std::vector<int> v;
// ...
{
std::vector<int> tmp(v); // create a copy of vector v
tmp.swap(v);
// vector tmp goes out of scope --> tmp is destroyed
}

或者简单地作为单行:

std::vector<int>(v).swap(v);

这个成语包括创建一个临时向量对象,该对象由原始向量v的元素组成,然后将生成的临时对象与原始向量交换v

应用这个成语交换生成的临时向量和v的能力。 如果生成的临时容量低于原始矢量v,这将导致v具有较低的容量。如果v.size()远低于v.capacity(),则很可能是这种情况。

取决于在哪些操作下。如果您包括所有这些,那么是的。

参见 [vector.capacity]p9 (shrink_to_fit(:

备注shrink_to_fit是一项不具约束力的请求,旨在将capacity()减少到size()。[注意:该请求不具有约束力,允许为特定于实现的优化留有余地。

和 [vector.capacity]p10 (swap(:

效果:将*this的内容和capacity()x的内容和交换。

换句话说,使用shrink_to_fit(),您可能会减少容量。使用swap(),只要您能够以较少的capacity()创建另一个vector,如果您swap()它们,则可以保证减少capacity()(但请注意,"原始"容量,即现在另一个对象的容量,本身不会减少(。


关于以下方面的快速说明:

所以我认为当一个向量的容量远大于它的大小时,它应该降低它的容量。我编写了以下代码来检查我的假设:

为了减少capacity(),实现需要(通常(分配内存(并移动/复制元素并释放原始存储(,这是一个非常昂贵的操作,在擦除元素时没有人想要。

最重要的是,如果您的程序随后再次达到其新capacity()(这很可能,因为您之前已经这样做了(,则必须再次重复该过程。