vector源码解析
//继承关系
class vector : protected _Vector_base<_Tp, _Alloc> ;
emplate <class _Tp, class _Alloc>
class _Vector_base {}
template <class _Tp, class _Allocator>
class _Vector_alloc_base<_Tp, _Allocator, true>
{
public:
typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type
allocator_type;
//获取空间配置器类型
allocator_type get_allocator() const { return allocator_type(); }
_Vector_alloc_base(const allocator_type&)
: _M_start(0), _M_finish(0), _M_end_of_storage(0)
{}
protected:
_Tp* _M_start;
_Tp* _M_finish;
_Tp* _M_end_of_storage;
};
_M_start是指向第一个元素的指针,等同于begin(),_M_finish是指向最后一个元素的下一个位置 _M_finish-_M_start=size();
_M_end_of_storage;等同于获取当前容器的容量,指向容器的最尾部。
vector迭代器其实是一个类对象指针,重载了一系列指针的操作。
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;
allocator_type get_allocator() const { return _Base::get_allocator(); }
//显示调用了父类的成员函数,获取空间配置器类型
//stl对其做了一个类型萃取
类型萃取帮助我们提取出自定义类型进行深拷贝,而内置类型统一进行浅拷贝,也就是所谓的值拷贝。
构造函数1
vector(size_type __n, const _Tp& __value)
: _Base(__n, __a)//对父类进行了构造
//typedef _Vector_base<_Tp, _Alloc> _Base;父类别名
//const allocator_type& __a = allocator_type());为了申请空间而服务的
{
_M_finish = uninitialized_fill_n(_M_start, __n, __value);
}
const allocator_type& __a = allocator_type();//缺省参数选择性忽略
vector空间配置器申请空间,_base(n,a);具体实现如下
_Vector_base(size_t __n, const allocator_type& __a) : _Base(__a)
{
_M_start = _M_allocate(__n);//申请空间
//-------------------函数实现--------------------------------
_Tp* _M_allocate(size_t __n)
{
return _M_data_allocator.allocate(__n);
}
//allocate实现如下
template <class T> inline T* allocate(ptrdiff_t size, T*)
{
set_new_handler(0);
T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));//申请内存空间
if (tmp == 0)
{
cerr << "out of memory" << endl;
exit(1);
}
return tmp;
}
//------------------------分割线实现如下------------------------
_M_finish = _M_start;
_M_end_of_storage = _M_start + __n;
}
构造函数2
可以传递一个范围,迭代器类型,或者内置类型初始化
vector(const _Tp* __first, const _Tp* __last)
: _Base(__last - __first, __a) //对空间申请进行操作,确定申请空间的范围
{
_M_finish = uninitialized_copy(__first, __last, _M_start);
//函数实现uninitialized_copy-------------------------------
}
//
inline char* uninitialized_copy(const char* __first, const char* __last, char* __result)
{
//进行内存拷贝操作
memmove(__result, __first, __last - __first);
return __result + (__last - __first);
}
构造函数3
可以传递一个vector来初始化
vector(const vector<_Tp, _Alloc>& __x)
: _Base(__x.size(), __x.get_allocator())
{
_M_finish = uninitialized_copy(__x.begin(), __x.end(), _M_start);
}
构造函数4
可以传递一个size_t类型的,来直接初始化一片空间为0
explicit vector(size_type __n)
: _Base(__n, allocator_type())
{
_M_finish = uninitialized_fill_n(_M_start, __n, _Tp());
}
赋值运算符重载
vector<_Tp, _Alloc>& operator=(const vector<_Tp, _Alloc>& __x);
void reserve(size_type __n)
{
if (capacity() < __n) //获取当前容量数量注1
{
const size_type __old_size = size();//获取老的元素个数
iterator __tmp = _M_allocate_and_copy(__n, _M_start, _M_finish);
//__tmp迭代器类型注2
destroy(_M_start, _M_finish);
//注3
_M_deallocate(_M_start, _M_end_of_storage - _M_start);
_M_start = __tmp;
_M_finish = __tmp + __old_size;
_M_end_of_storage = _M_start + __n;
}
}
注1:
从性能考虑,重新分配内存空间效率不高。如果预先知道元素的数量,可以使用reserve()函数来消除重新分配。
注2:
iterator _M_allocate_and_copy(size_type __n, const_iterator __first,
const_iterator __last)
{
iterator __result = _M_allocate(__n);
__STL_TRY
{
uninitialized_copy(__first, __last, __result);
return __result;
}
__STL_UNWIND(_M_deallocate(__result, __n));
}
注3:
template <class _Tp>
inline void _Destroy(_Tp* __pointer)
{
__pointer->~_Tp();
}
Increase the capacity of the vector to a value that’s greater or equal to new_cap
. If new_cap
is greater than the current capacity(), new storage is allocated, otherwise the method does nothing.
reserve() does not change the size of the vector.
尝试将把vector扩容到大于或等于new_cap。
如果new_cap大于当前容量,则重新分配。
**reserve()**并不改变vector。
这里涉及到vector的优化策略
将原有空间进行扩容,并不重新分配空间,将原来空间中的数据清空。
insert函数的动态扩容
insert函数在vector中至关重要,push_back()的动态扩容和insert有很大区别
先抛出结论
insert不知道需要插入多个元素,如果按照sizex2去扩容,一旦插入数据过多,会需要扩容很多造成效率上的降低。
Linux系统下经过测试
t是当前元素个数–m=要插入的个数,n是总容量,m是待插入个数
insert 方式1,插入单个数据,无需考虑上述过程
iterator insert(iterator __position, const _Tp& __x)
{
size_type __n = __position - begin();//从要插入的位置,计算好距离begin()的偏移
if (_M_finish != _M_end_of_storage && __position == end())
{//如果是在尾部进行插入,并且当前容量够用的情况下
//如果不是vector数组本身之后的位置,就证明肯定容量是够用的
construct(_M_finish, __x);//注4
++_M_finish;//在中间插入的,偏移一次,继续指向最后一个元素的下一个元素
}
else
{ //在尾部进行插入
_M_insert_aux(__position, __x);//注5
}
return begin() + __n;
}
注4:
template <class _T1, class _T2>
inline void construct(_T1* __p, const _T2& __value) {
_Construct(__p, __value);
}
//第一层调用
template <class _T1, class _T2>
inline void _Construct(_T1* __p, const _T2& __value)
{
new ((void*) __p) _T1(__value);//new定位符,在指定空间申请内存
//直接构建对象
}
//第二层调用
注5:
M_insert_aux动态扩容实现
template <class _Tp, class _Alloc>
void
vector<_Tp, _Alloc>::_M_insert_aux(iterator __position, const _Tp& __x)
{
if (_M_finish != _M_end_of_storage) //如果当前容量仍然够用的情况下
{
construct(_M_finish, *(_M_finish - 1));//申请空间
++_M_finish;//将其后移,始终指向当前最后一个元素的下一个点
_Tp __x_copy = __x;//将传进来待插入的value保存好
copy_backward(__position, _M_finish - 2, _M_finish - 1);
//注6
*__position = __x_copy;
}
else //容量不足的情况下需要考虑申请空间了
{
const size_type __old_size = size();
const size_type __len = __old_size != 0 ? 2 * __old_size : 1;
iterator __new_start = _M_allocate(__len);
iterator __new_finish = __new_start;
__STL_TRY {
__new_finish = uninitialized_copy(_M_start, __position, __new_start);
construct(__new_finish, __x);
++__new_finish;
__new_finish = uninitialized_copy(__position, _M_finish, __new_finish);
}
__STL_UNWIND((destroy(__new_start,__new_finish),
_M_deallocate(__new_start,__len)));
destroy(begin(), end());
_M_deallocate(_M_start, _M_end_of_storage - _M_start);
_M_start = __new_start;
_M_finish = __new_finish;
_M_end_of_storage = __new_start + __len;
}
}
注6
功能:将每个元素都往后移动一位,直到要插入的位置
template <class _BI1, class _BI2>
inline _BI2 copy_backward(_BI1 __first, _BI1 __last, _BI2 __result)
{
return __copy_backward(__first, __last, __result,
__ITERATOR_CATEGORY(__first),
__DISTANCE_TYPE(__first));
}
//第一层调用
template <class _BidirectionalIter1, class _BidirectionalIter2,
class _Distance>
inline _BidirectionalIter2 __copy_backward(_BidirectionalIter1 __first,
_BidirectionalIter1 __last,
_BidirectionalIter2 __result,
bidirectional_iterator_tag,
_Distance*)
{
while (__first != __last)
*--__result = *--__last;
return __result;
}
//第二层调用