STL矢量实现

时间:2013-12-12 15:45:44

标签: c++ c++11 vector stl

我想知道STL std::vector是如何实现的。

确切地说,STL向量是否包含对象表或指向对象的表?

在实际实施中:最好是std::vector<char>的大小是10^8,还是数组为char

第一个选项有明显的优点:迭代就像在其他所有容器中一样,已知大小,自动内存管理,很难做错事。

第二个选项可以使用9倍的空间(指针是64位,其中char是8位),但代价是上面列出的所有舒适方法。

我调查了一下 /usr/include/c++/4.8.2/bits/stl_vector.h 并看到push_back()实现如下,但即使检查alloc_traits.h也不知道它是如何真正完成的。

类型char仅用于表示指针的大小与保持的值大小相比是显着的。

我正在使用C ++ 11。

void
push_back(const value_type& __x)
{
     if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
     {
         _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
                                  __x);
         ++this->_M_impl._M_finish;
     }
     else
#if __cplusplus >= 201103L
     _M_emplace_back_aux(__x);
#else
     _M_insert_aux(end(), __x);
#endif
}

3 个答案:

答案 0 :(得分:8)

向量管理单个连续的对象数组,因此它不需要指向每个元素的指针。它只需要:

  • 指向数组开头的指针
  • 标记所用元素结尾的指针(或索引)(即大小)
  • 标记已分配存储结束的指针(或索引)(即容量)

(它还需要存储一个分配器;但通常情况下,这是无状态的,一个不错的实现将使用“空基类优化”来确保它在这种情况下不占用空间)。

如果您管理自己的动态阵列,则至少需要其中两个;所以使用矢量的额外成本是一个指针。

如果您不需要动态分配,那么自动数组(或std::array,如果您想要更多STLy)将更有效:它不会涉及任何堆分配或任何额外存储。但是,只有在编译时知道大小时才有可能,并且存在大型数组可能溢出堆栈的危险。

答案 1 :(得分:3)

std :: vector保存一个连续的存储块,动态(重新)分配。 把它想象成是:

struct vector { size_t size, capacity; void *data; };

答案 2 :(得分:2)

std::vector<T>在保证的连续缓冲区中保存一系列类型为T的对象。

关于问题

  

在实际实现中:使用大小约为10 ^ 8的std :: vector或者使用char数组是否更好?

这个大小本身就无关紧要了。

但是,如果您将一个大型char数组分配为本地自动变量,那么很可能您的堆栈空间不足,具有非常未定义的行为。您可以通过动态分配数组来避免这种情况。一种合理的方法是使用std::string(或std::vector,但很可能这是一个字符串。)