c ++ vector如何工作

时间:2012-06-13 22:14:56

标签: c++ stl

让我们说如果我有一个矢量V,它有10个元素。 如果我使用v.erase(v.begin())擦除第一个元素(在索引0处),那么STL向量如何处理这个?

它是否会创建另一个新的向量并将元素从旧向量复制到新向量并释放旧向量?或者它是否从索引1开始复制每个元素并将元素复制到index-1?

如果我需要一次使用大小为100,000的向量,之后我不会使用那么多空间,我可以说我只需要一个大小为10的向量然后它会自动减小大小吗? (我不这么认为)

我在线查看,只有API和教程如何使用STL库。 是否有任何好的参考资料可以让我了解STL库的实现或复杂性?

5 个答案:

答案 0 :(得分:5)

实际上,vector的实现是可见的,因为它是一个模板,因此您可以查看详细信息:

iterator erase(const_iterator _Where)
    {   // erase element at where
    if (_Where._Mycont != this
        || _Where._Myptr < _Myfirst || _Mylast <= _Where._Myptr)
        _DEBUG_ERROR("vector erase iterator outside range");
    _STDEXT unchecked_copy(_Where._Myptr + 1, _Mylast, _Where._Myptr);
    _Destroy(_Mylast - 1, _Mylast);
    _Orphan_range(_Where._Myptr, _Mylast);
    --_Mylast;
    return (iterator(_Where._Myptr, this));
    }

基本上,行

unchecked_copy(_Where._Myptr + 1, _Mylast, _Where._Myptr);

完全按照你的想法 - 将以下元素复制(或者在B ++ 53指出的C ++ 11中移动它们)。

要回答你的第二个问题,不,容量不能自行降低。

std中算法的复杂性可以在http://www.cplusplus.com/reference/stl/找到,如前所述,实现是可见的。

答案 1 :(得分:1)

  

它是否从索引1开始复制每个元素并将该元素复制到index-1?

是的(虽然它实际上是从C ++ 11开始移动它们)。

  

会自动缩小尺寸吗?

不,减小大小通常会使现有元素的迭代器无效,并且只允许在某些函数调用上使用。

  

我在线查看,只有API和教程如何使用STL库。是否有任何好的参考资料可以让我了解STL库的实现或复杂性?

您可以阅读C ++规范,该规范将准确地告诉您允许的内容和实现方面的内容。您还可以查看实际实施情况。

答案 2 :(得分:1)

Vector会将元素复制(在C ++ 11中移动)到开头,这就是为什么你应该使用deque,如果你想从集合的开头插入和删除。如果你想真正调整向量的内部缓冲区大小,你可以这样做:

vector<Type>(v).swap(v);

这将有希望制作一个具有正确大小的临时向量,然后将其内部缓冲区与旧缓冲区交换,然后临时向量超出范围,大缓冲区将被释放。

正如其他人所说,您可以在C ++ 11中使用vector::shrink_to_fit()

答案 3 :(得分:0)

这是我(很多)对C ++的反对意见之一。每个人都说“使用标准库”......但即使你有STL源(可以从许多不同的地方免费获得。包括,在这种情况下,头文件本身!)......这基本上是一个难以理解的噩梦挖掘并尝试理解。

(仅限C语言)Linux内核是简洁明了的典范。

但我们离题了:))

这是你问题的10,000英尺答案:

  

http://www.cplusplus.com/reference/stl/vector/

     

Vector容器实现为动态数组;和常规一样   数组,向量容器的元素存储在连续的中   存储位置,这意味着不能访问它们的元素   只使用迭代器,但也使用常规指针上的偏移量   元件。

     

但与常规数组不同,处理向量中的存储   自动,允许根据需要进行扩展和收缩。

     

矢量擅长:

     
      
  • 按位置索引(恒定时间)访问各个元素。
  •   
  • 以任意顺序(线性时间)迭代元素。
  •   
  • 从结尾添加和删除元素(常量摊销时间)。
  •   
     

与阵列相比,它们为这些阵列提供了几乎相同的性能   任务,加上他们有能力轻松调整大小。虽然,他们   处理容量时,通常比数组消耗更多内存   自动(这是为了容纳额外的存储空间)   未来增长)。

     

与其他基本标准序列容器相比(deques和   列表),向量通常是最有效的访问时间   元素以及从序列末尾添加或删除元素。   对于涉及插入或删除元素的操作   除了结尾之外的位置,它们的表现比deques和   列表,并且具有比列表更不一致的迭代器和引用。

     

...

     

从性能方面来看,重新分配可能是一项代价高昂的操作   它们通常涉及向量使用的整个存储空间   被复制到一个新的位置。您可以使用成员函数   vector :: reserve预先指示向量的容量。这个   可以帮助优化存储空间并减少重新分配的数量   当计划进行多次扩建时。

     

...

答案 4 :(得分:-1)

  

我只需要一个10号的矢量然后自动减小尺寸?

不,它不会自动缩小。
传统上,您将向量与新的空格交换:reduce the capacity of an stl vector

但是C ++ x11包含一个std :: vector :: shrink_to_fit()它可以直接执行它