这里引用源码中的一段描述
In some terminology a %vector can be described as a dynamic C-style array, it offers fast and efficient access to individual elements in any order and saves the user from worrying aboutmemory and size allocation.
vector毫不夸张得说就是有动态内存分配功能的传统数组。vector中包含三个关键成员变量,
_M_start
指向第一个元素的位置,同时也是连续内存的起始地址。_M_finish
指向存储的最后一个元素的后一个位置。所以当vector.empty() == true
时,_M_start == _M_finish
。_M_end_of_storage
存储的是连续内存内存地址的末尾地址的后一个位置。
pointer _M_start;
pointer _M_finish;
pointer _M_end_of_storage;
通过begin(), end(), size(), empty(), capacity()
函数实现我们便能更加深刻得理解这三个指针的意义。
const_iterator
begin() const _GLIBCXX_NOEXCEPT
{
return const_iterator(this->_M_impl._M_start); }
const_iterator
end() const _GLIBCXX_NOEXCEPT
{
return const_iterator(this->_M_impl._M_finish); }
size_type
size() const _GLIBCXX_NOEXCEPT
{
return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); }
bool
empty() const _GLIBCXX_NOEXCEPT
{
return begin() == end(); }
size_type
capacity() const _GLIBCXX_NOEXCEPT
{
return size_type(this->_M_impl._M_end_of_storage
- this->_M_impl._M_start); }
vector的关键就是内存的动态分配和释放如何实现,其涉及内存分配的操作主要有construct、insert、push_back,operator=。
construct
对于构造函数vector()
,其存在如下调用路径。其结果就是三个指针全部指向nullptr。
vector()
: _Base() {
}
_Vector_base()
: _M_impl() {
}
_Vector_impl()
: _Tp_alloc_type(), _M_start(), _M_finish(), _M_end_of_storage()
{
}
对于构造函数vector( size_type count, const T& value, const Allocator& alloc = Allocator())
,此函数中内存分配的任务是在_M_create_storage
中分配,其分配了__n大小的连续内存空间,并设置了三个指针的位置。而对于其地址的初始化任务则交由_M_fill_initialize完成。此函数对数组中每个空间调用placement new operator,来对其空间进行构造。
vector(size_type __n, const value_type& __value,
const allocator_type& __a = allocator_type())
: _Base(__n, __a)
{
_M_fill_initialize(__n, __value); }
_Vector_base(size_t __n, const allocator_type& __a)
: _M_impl(__a)
{
_M_create_storage(__n); }
_M_create_storage(size_t __n)
{
this->_M_impl._M_start = this->_M_allocate(__n);
this->_M_impl._M_finish = this->_M_impl._M_start;
this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n