c++中关于std::vector的基本问题

basic question on std::vector in C++

本文关键字:问题 vector c++ std      更新时间:2023-10-16

c++教科书和线程都说vector元素在内存中是物理上连续的。

但是当我们做像v.push_back(3.14)这样的操作时,我会假设STL使用new操作符来获得更多的内存来存储刚刚引入向量的新元素3.14。

现在假设大小为4的向量存储在标记为0x7, 0x8, 0x9, 0xA的计算机内存单元中。如果单元格0xB包含一些其他不相关的数据,3.14如何进入这个单元格?这是否意味着单元格0xB将被复制到其他地方,擦除以为3.14腾出空间?

简短的回答是,保存向量数据的整个数组被移动到一个有空间可以增长的位置。vector类保留了一个比技术上容纳vector中元素数量所需的更大的数组。例如:

vector< int > vec;
for( int i = 0; i < 100; i++ )
    vec.push_back( i );
cout << vec.size(); // prints "100"
cout << vec.capacity(); // prints some value greater than or equal to 100

capacity()方法返回vector所保留的数组的大小,而size()方法返回数组中实际使用的元素的数量。capacity()将始终返回一个大于或等于size()的数字。您可以使用reserve()方法来更改后备数组的大小:

vec.reserve( 400 );
cout << vec.capacity(); // returns "400"

注意,size()capacity()reserve()和所有相关的方法都指向vector所保存的类型的单个实例。例如,如果vec的类型参数T是一个占用10字节内存的结构体,那么vec.capacity()返回400意味着该向量实际上保留了4000字节的内存(400 x 10 = 4000)。

那么,如果向vector中添加的元素超过了vector的容量,会发生什么情况呢?在这种情况下,vector分配一个新的后备数组(通常是旧数组大小的两倍),将旧数组复制到新数组中,然后释放旧数组。在伪代码:

if(capacity() < size() + items_added)
{
    size_t sz = capacity();
    while(sz < size() + items_added) 
       sz*=2;
    T* new_data = new T[sz]; 
    for( int i = 0; i < size(); i++ )
        new_data[ i ] = old_data[ i ];
    delete[] old_data;
    old_data = new_data;
}

因此整个数据存储被移动到内存中的一个新位置,该位置有足够的空间来存储当前数据和一些新元素。

如果分配的空间比实际需要的空间大得多,一些向量也可以动态地减小其后台数组的大小。

std::vector首先分配一个更大的缓冲区,然后将"旧"缓冲区中的现有元素复制到"新"缓冲区中,然后删除"旧"缓冲区,最后将新元素添加到"新"缓冲区中。

一般来说,std::vector实现通过每次需要分配更大的缓冲区时将容量增加一倍来增长它们的内部缓冲区。

正如Chris提到的,每次缓冲区增长时,所有现有的迭代器都会失效。

当std::vector为值分配内存时,它分配的内存比实际需要的要多;你可以通过调用capacity来了解多少。当该容量用完时,它会分配一个更大的块,同样比它需要的大,并将所有内容从旧内存复制到新内存;然后释放旧内存

如果没有足够的空间来添加新元素,则会分配更多的空间(正如您正确指出的那样),并将旧数据复制到新位置。因此单元格0xB将仍然包含旧的值(因为它可能在其他地方有指向它的指针,不可能在不造成破坏的情况下移动它),但是有问题的整个向量将被移动到新位置。

vector是一种内存数组。典型的实现是它获取比所需更多的内存。如果该内存占用需要扩展到任何其他内存,那么整个内存都会被复制。旧的东西被释放了。向量内存在堆栈上——这一点应该注意。说明需要最大尺寸也是一个好主意。

在来自C的c++中,内存不是按照您描述的方式"管理"的- Cell 0x0B的内容不会被移动。如果这样做,任何现有的指针都将无效!(唯一可能的情况是,该语言没有指针,只使用类似功能的引用。)

std::vector分配了一个新的更大的缓冲区,并将3.14的值存储到缓冲区的末尾。

通常,对于优化的this->push_back() s, std::vector分配的内存大约是this->size()的两倍。这确保了以合理数量的内存交换性能。因此,不能保证3.14会导致this->resize(),当且仅当this->size() < this->capacity() .

可以简单地放入this->buffer[this->size()++]