我们知道,为了实现高效的随机访问,容器中的元素应该是物理上和逻辑上连续存储的。因此如果我们想容器中添加新的元素,会发生什么呢?容器会分配新的空间来保存已有的元素和新的元素,再将已有的元素从旧容器中拷贝过来,在添加新的元素,释放旧的空间。如果我们没添加一个新的元素就进行一次这样的操作,那么性能将会慢到我们不可接受。那么标准库容器采用了什么样的策略来减少内存重新分配的次数呢?
当容器不得不进行如上操作是,容器通常会开辟一个比新空间更大的内存空间。容器预留这些空间作为备用,因此我们如果再次插入新的元素的话,就不需要再次添加新的元素来重新分配容器空间了。
这种分配策略比每次添加元素时都重新分配容器内存空间的策略要高效很多。其实际性能也表现的足够好——虽然vector在每一次重新分配内存空间后都要移动元素,但是使用此策略后,其扩张操作(push_back)通常要比list和deque容器快。
vector和string类型提供了一些成员函数,允许我吗与它的实现中内存分配部分互动。
| c.capacity() | 不重新分配内存的话,c最多可以保存多少元素 |
|---|---|
| c/shrink_to_fit() | 将capacity()减少到与size()相同的大小 |
| c.reserve(n) | 分配至少能够容纳n个元素的内存空间 |
注意::shrink_to_fit()只适用于deque、string、vector容器
capacity()、reserve()只适用于vector和string容器
只有当需要的内存空间超过当前容量时,reserve调用才会改变vector的容量。如果需求大于当前容量,那么reserve至少会分配与需求一样大的空间。即内存不会退回内存空间,在调用reserve时,capacity将会大于或等于传递给reserve的参数。
如果需求等于当前容量,那么reserve什么也不做。
注意: 调用reserve永远也不会减少容器占用的内存空间。类似的,resize成员函数只改变容器中的元素数目,而不会改变容器容量。我们同样不能用resize成员函数来减少容器的预留空间。



