调整保留std::vector大小时的c++内存分配

C++ memory allocation upon resizing of reserved std::vector

本文关键字:c++ 内存 分配 小时 保留 std vector 调整      更新时间:2023-10-16

我对std::vector行为很好奇,我在任何地方都找不到答案,所以…

让我们有一个奇数程序:

std::vector<int> vec;
vec.reserve(5);
for(int i = 0; i < vec.size(); ++i) // OK, I have noticed the mistake in the condition, I am leaving it here for educational purposes
{
    vec.resize(vec.size() + 1);
    vec[i] = 42;
}

内存分配方面的行为是什么?只按预期分配一次内存,还是调整大小清除不需要的内存?

对于初学者,这个循环将永远不会执行

std::vector<int> vec;
vec.reserve(5);
for(int i = 0; i < vec.size(); ++i)
{
    vec.resize(vec.size() + 1);
    vec[i] = 42;
}

因为初始向量的大小等于0

也许你的意思是像下面这样

std::vector<int> vec;
vec.reserve(5);
for(int i = 0; i < vec.capacity(); ++i)
{
    vec.resize(vec.size() + 1);
    vec[i] = 42;
}

在这种情况下,vector将不会被重新分配:)

下面是一个示范程序

#include <iostream>
#include <vector>
int main()
{
    const size_t N = 5;
    std::vector<int> v;
    v.reserve( N );
    std::vector<int>::size_type i = 0;
    do
    {
        v.resize( v.size() + 1);
        std::cout << v.capacity() << 't' << v.data() << std::endl;
    } while ( ++i < v.capacity() );
    return 0;
}

它的输出可能看起来像

5   0x824da10
5   0x824da10
5   0x824da10
5   0x824da10
5   0x824da10

reserve方法实际做的是:

请求向量容量至少足以包含n元素。

  • 如果n大于当前向量容量,则该函数使容器重新分配其存储空间,使其容量增加到n(或更大)。

  • 在所有其他情况下,函数调用不会导致重新分配,并且向量容量不受影响。

  • 此函数对向量大小没有影响,也不能改变其元素。

因此,首先,vec.reserve(5);将为5元素分配内存。(但是向量的大小仍然是0)

然后,在循环内部,你调用vec.resize(vec.size() + 1);,让我们首先看看,这个函数做什么:

resize实际做的是:

调整容器的大小,使其包含n个元素。

  • 如果n小于当前容器大小,则内容将减少到其第一个n元素,并删除超出的元素(并销毁它们)。

  • 如果n大于当前容器的大小,则根据需要在末尾插入元素来扩展内容,以达到n大小。如果指定了val,则将新元素初始化为val的副本,否则将它们进行值初始化。

  • 如果n也大于当前容器容量,则自动重新分配已分配的存储空间。

  • 注意,这个函数通过插入或删除元素来改变容器的实际内容。

在你的例子中,程序,In循环总是传递n,它比vec capacity 低,所以,不会执行内存分配,只有 size 属性会被改变。

reserve分配空间来容纳请求的项数。resize告诉vector容器中当前有多少项。

因此,如果您保留较少,那么您将使用resize指定分配。

如果您保留的大于您调整大小的值,则后续调整大小不需要额外的分配。

vec.size()一开始就是0。vec.reserve(5)将为至少5个元素分配空间。这样循环就什么也不做了。

但是让我们假设你想循环到5。只有reserve调用才会为vector分配更多内存。循环内的resize操作,由于小于或等于vector容器的容量,只会在已经分配的空间中构造新元素。