我想知道STL std::vector
是如何实现的。
确切地说,STL向量是否包含对象表或指向对象的表?
在实际实施中:最好是std::vector<char>
的大小是10^8
,还是数组为char
?
第一个选项有明显的优点:迭代就像在其他所有容器中一样,已知大小,自动内存管理,很难做错事。
第二个选项可以使用9倍的空间(指针是64位,其中char
是8位),但代价是上面列出的所有舒适方法。
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
}
答案 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
,但很可能这是一个字符串。)