C++ STL向量';实施

C++ STL向量';实施,c++,c++11,vector,stl,C++,C++11,Vector,Stl,我想知道STLstd::vector是如何实现的 确切地说,STL向量是包含对象表还是指向对象的指针表 在实际实现中:最好是使用大小约为10^8的std::vector,还是使用char数组 第一个选项有明显的优点:像在其他容器中一样迭代,已知大小,自动内存管理,很难做一些真正错误的事情 第二个选项使用的空间可能要少9倍(指针是64位,其中char是8位),但代价是上面列出的所有舒适的方法 我调查 /usr/include/c++/4.8.2/bits/stl_vector.h 看到了push_

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

确切地说,STL向量是包含对象表还是指向对象的指针表

在实际实现中:最好是使用大小约为
10^8
std::vector
,还是使用
char
数组

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

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

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

Type
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
}

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

struct vector { size_t size, capacity; void *data; };
std::vector
在保证连续的缓冲区中保存类型为
T
的对象序列

关于这个问题

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

大小本身并不重要


但是,如果您将大量
char
数组作为本地自动变量进行分配,那么很可能会耗尽堆栈空间,导致行为非常不明确。可以通过动态分配数组来避免这种情况。一种合理的方法是使用
std::string
(或者
std::vector
,但很可能这是一个字符串)。

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

  • 指向数组开头的指针
  • 标记所用元素结束的指针(或索引)(即大小)
  • 标记已分配存储(即容量)结束的指针(或索引)
(它还需要存储一个分配器;但通常情况下,这是无状态的,一个合适的实现将使用“空基类优化”,以确保在这种情况下不占用任何空间)

如果您管理自己的动态数组,则至少需要其中两个;因此,使用向量的额外成本是一个指针


如果您不需要动态分配,那么自动数组(或
std::array
,如果您需要更复杂的内容)将更加高效:它不涉及任何堆分配或任何额外存储。但是,只有在编译时知道大小的情况下才有可能,并且存在一个大数组可能溢出堆栈的危险。

否,它不包含指向元素的指针。包含10^8个元素的
向量
的簿记占用空间可以忽略不计。它实际上不包含
大小
,而是一个指向存储结尾的指针。@tobias:它如何表示大小取决于实现。