它是一个简单的模板类,它包装了一个原生数组。它不使用malloc/realloc。相反,它使用传递的分配器(默认为std::allocator)。
调整大小是通过分配一个新数组并从旧数组复制构造新数组中的每个元素来完成的(这样对非 POD 对象是安全的)。为了避免频繁分配,它们通常遵循非线性增长模式。
更新:在 C++11 中,如果存储类型可能,元素将被移动而不是复制构造。
除此之外,它还需要存储当前的“大小”和“容量”。大小是向量中实际有多少元素。容量是向量中可以的数量。
因此,作为起点,向量需要看起来像这样:
template <class T, class A = std::allocator<T> >
class vector {
public:
// public member functions
private:
T* data_;
typename A::size_type capacity_;
typename A::size_type size_;
A allocator_;
};
另一个常见的实现是存储指向数组不同部分的指针。这降低了end()(不再需要添加)的成本,但代价是稍微昂贵的size()调用(现在需要减法)。在这种情况下,它可能如下所示:
template <class T, class A = std::allocator<T> >
class vector {
public:
// public member functions
private:
T* data_; // points to first element
T* end_capacity_; // points to one past internal storage
T* end_; // points to one past last element
A allocator_;
};
我相信 gcc 的 libstdc++ 使用后一种方法,但两种方法同样有效且符合要求。
注意:这忽略了一个常见的优化,其中空基类优化用于分配器。我认为这是实现细节的质量,而不是正确性的问题。