STL vector详解
- 1. 简介
- 2. vector的内存机制
- 3. vector 基类源码_Vector_base
- 3.1. vector 基类成员变量
- 3.2. vector 基类方法
- 3.3. _Vector_base 总结
- 4. vector类
- 4.1. 方法
1. 简介
本文参考vector源码,主要介绍vector的设计思路,了解一些方法的实现原理,内存机制。
2. vector的内存机制
模板类vector是一种动态数组。在运行阶段可以设置vector对象的长度,可在末尾添加新数据,还可以在中间插入新数据。vector使用new和delete来管理内存,但这种工作是自动完成的,每次内存不够会自动开辟一段新的空间,自动开辟的空间大小是原空间大小的2倍,如果第一次开辟因为原来没有开辟空间就开辟1个字节的空间。
3. vector 基类源码_Vector_base
源码如下:
template <class _Tp, class _Alloc>
class _Vector_base {
public:typedef _Alloc allocator_type;allocator_type get_allocator() const { return allocator_type(); }_Vector_base(const _Alloc&): _M_start(0), _M_finish(0), _M_end_of_storage(0) {}_Vector_base(size_t __n, const _Alloc&): _M_start(0), _M_finish(0), _M_end_of_storage(0) {_M_start = _M_allocate(__n);_M_finish = _M_start;_M_end_of_storage = _M_start + __n;}~_Vector_base() { _M_deallocate(_M_start, _M_end_of_storage - _M_start); }protected:_Tp* _M_start;_Tp* _M_finish;_Tp* _M_end_of_storage;typedef simple_alloc<_Tp, _Alloc> _M_data_allocator;_Tp* _M_allocate(size_t __n){ return _M_data_allocator::allocate(__n); }void _M_deallocate(_Tp* __p, size_t __n) { _M_data_allocator::deallocate(__p, __n); }
};
3.1. vector 基类成员变量
_Tp* _M_start; //vector存储数据存储的首地址_Tp* _M_finish; //vector存储数据存储的尾地址+1 其实就是vector::end()返回的迭代器_Tp* _M_end_of_storage; //vector占用内存的尾地址
其实vector中只有三个指针成员因此sizeof一个vector对象的大小就是sizeof指针大小的三倍,32bit系统和64bit系统可能会有一些差别。64bit系统中vector占用内存空间为3*8=24字节。
3.2. vector 基类方法
构造函数
_Vector_base(const _Alloc&) // 指定一个空间配置器: _M_start(0), _M_finish(0), _M_end_of_storage(0) {}_Vector_base(size_t __n, const _Alloc&) //指定vector 空间大小__n*sizeof(_Tp) 指定一个空间配置器: _M_start(0), _M_finish(0), _M_end_of_storage(0) {_M_start = _M_allocate(__n); //这行代码相当于开辟了n*sizeof(_Tp) (_Tp是vector中存储类型)这么大的空间_M_finish = _M_start; //没有成员时finish = start_M_end_of_storage = _M_start + __n; //vector占用内存的尾地址}
allocator_type get_allocator() const { return allocator_type(); } //获取空间配置器类型_Tp* _M_allocate(size_t __n); //开辟空间void _M_deallocate(_Tp* __p, size_t __n); //释放空间
3.3. _Vector_base 总结
通过两个构造函数就可以知道,构造_Vector_base 时需要指定空间配置器同时也可以指定size,如果指定了size就会开辟sizesizeof(_Tp)这么大的空间,_M_start 指针指向这块空间的首地址,_M_finish 和_M_start 指向同一块地址(因为目前虽然开辟了空间但是并没有向vector中存入数据)。_M_start 指向的是vector中存入数据的首地址,_M_finish指向的是vector中存入数据的尾地址+1(其实就是vector::end()返回的迭代器),_M_end_of_storage就是vector内开辟空间的尾地址+1,也就是(vector::capacity()返回的值)
下图为_M_start ,_M_finish ,_M_end_of_storage指针在vector中所指向的内存位置示意图使用的是vector<int32_t>
下图vector中开辟了44个字节的空间(相当于调用vector<int32_t>::reserve(4)),并且向vector中插入了2个int32_t值1,2。
4. vector类
其实vector源码中_Vector_base 类的源码就可以展示出vector的设计思路也是精华部分,vector类中的方法主要提供给用户使用vector,因此vector那部分源码就不展示了感兴趣的可以自己去看看。
vector类中没有任何成员,继承了_Vector_base 类提供了一些公有的方法,下面主要说明下vector中的公有方法
4.1. 方法
首先了解下vector中typedef的部分类型
typedef _Tp value_type;typedef value_type* pointer;typedef const value_type* const_pointer;typedef value_type* iterator; //迭代器其实就是指针typedef const value_type* const_iterator;typedef value_type& reference; //引用typedef const value_type& const_reference;typedef size_t size_type;typedef ptrdiff_t difference_type;
vector的构造函数
explicit vector(const allocator_type& __a = allocator_type()) //可以指定空间配置器,也可以使用默认的空间配置器: _Base(__a) {}vector(size_type __n, const _Tp& __value,const allocator_type& __a = allocator_type()) //可以指定vector成员个数和初始化成员的值: _Base(__n, __a){ _M_finish = uninitialized_fill_n(_M_start, __n, __value); }explicit vector(size_type __n) //可以指定vector成员个数,指定个数同时就会开辟对应的空间sizeof(_Tp)*__n: _Base(__n, allocator_type()){ _M_finish = uninitialized_fill_n(_M_start, __n, _Tp()); }vector(const vector<_Tp, _Alloc>& __x) //拷贝构造: _Base(__x.size(), __x.get_allocator()){ _M_finish = uninitialized_copy(__x.begin(), __x.end(), _M_start); }vector(const _Tp* __first, const _Tp* __last,const allocator_type& __a = allocator_type()) //从迭代器的__first位置拷贝到迭代器__last位置: _Base(__last - __first, __a) //相当于在基类里面创建了一个__last - __first这么大的空间{ _M_finish = uninitialized_copy(__first, __last, _M_start); }
函数 | 描述 |
---|---|
iterator begin() | 获取_M_start位置的迭代器也就是vector开辟内存的起始指针有个重载返回的是const 的_M_start位置的迭代器 |
const_iterator cbegin() | 返回的是一个const 的_M_start位置的迭代器 |
iterator end() | 获取_M_finish位置的迭代器也就是vector内尾成员后一个位置的指针,有个重载返回的是const 的_M_finish位置的迭代器 |
const_iterator cend() | 返回的是一个const 的_M_finish位置的迭代器 |
reverse_iterator rbegin() | 返回的是一个reverse_iterator内部存储_M_finish位置的迭代器,但是里面实现很多重载操作符比如operator*()实际返回的是_M_finish位置前一个位置的内容返回值类似 * - - _M_finish |
const_reverse_iterator crbegin() | 返回const_reverse_iterator |
reverse_iterator rend() | 返回的是一个reverse_iterator内部存储_M_start位置的迭代器,但是里面实现很多重载操作符比如operator*()实际返回的是_M_start位置前一个位置的内容返回值类似 * - - _M_start |
const_reverse_iterator crend() | 返回const_reverse_iterator |
size_type size() | 返回的是_M_finish-_M_start也就是vector中实际存储的成员个数 |
size_type max_size() | 返回vector所能储存的最大的元素数目,容器所能容纳的最大元素数目,这是系统或者库所实施的限制。但是容器不一定保证能达到该大小,有可能在还未达到该大小的时候,就已经无法继续分配任何的空间了。 |
size_type capacity() | 返回容器的容量(开辟空间大小/sizeof(_Tp))比如vector<int32_t>如果返回的是10也就代表当前容量最多可以存储10个uint32_t也就是开辟了4*10这么大空间 |
bool empty() | 返回的是begin()==end() 也就是容器是否是空 |
reference operator[](size_type __n) | 返回的是一个*(begin()+__n)引用 还有个重载返回的是一个const 引用 |
void reserve(size_type __n)() | 设置vector容量为__n及如果当前容量小于__n则需要开辟到__n*sizeof(_Tp)(这么大就可以存储__n个_Tp类型的对象),如果当前容量大于__n则直接返回 |
void assign(size_type __n, const _Tp& __val) | 给vector填充__n个 值为__val 的数据 |
template < class _InputIterator> void assign(_InputIterator __first, _InputIterator __last) | 给vector重新填充数据从迭代器__first到迭代器__last,set的begin(),end()填入该函数可以将set的值赋值给vector |
reference front() | 返回一个*begin()也就是返回vector中起始位置的引用 |
const_reference front() | 返回一个*begin()也就是返回vector中起始位置的const 引用 |
reference back() | 返回一个*(end()-1)也就是返回vector中末尾位置的引用 |
const_reference back() | 返回一个*(end()-1)也就是返回vector中末尾位置的const 引用 |
void push_back(const _Tp& __x) | 在vector末尾插入一个值,现在可以使用emplace_back代替,emplace_back效率更高少一次拷贝 |
void emplace_back(_Args&&… __args) | 在vector末尾插入一个值 |
template< typename _InputIterator> void insert(iterator __position, _InputIterator __first, _InputIterator __last) | 在指定位置插入从__first到__last之间的所有值并返回__first插入位置的迭代器 |
iterator insert(const_iterator __position, size_type __n, const value_type& __x) | 在指定位置插入n个值为__x的值并返回第一个插入位置的迭代器 |
iterator insert(const_iterator __position, initializer_list<value_type> __l) | 在指定位置插入一个C风格的数组并返回第一个插入位置的迭代器 |
iterator insert(const_iterator __position, const value_type& __x) | 在指定位置插入该值并返回该位置的迭代器 |
iterator emplace(const_iterator __pos, _Args&&… __args) | 在指定位置插入该值并返回该位置的迭代器 |
iterator erase(iterator __position) | 删除指定位置的值,返回的迭代器指向删除的值的下一个位置 |
void swap(vector& __x) | 当前vector和参数中的vector里面的值进行交换 |
void clear() | 清空vector |