成员变量:
pointer _Myfirst; // pointer to beginning of array
pointer _Mylast; // pointer to current end of sequence
pointer _Myend; // pointer to end of array
_Alty _Alval; // allocator object for values
对于void push_back(_Ty &&_Val)函数,会判断push_back的对象是否在vector内部(是否在内部只有在将新成员添加到vector时的传参有区别,其他没啥区别,就不分开描述了)。
首先,判断当前的大小是否足够添加成员,若已满,则_Reserve(1),申请新的内存空间。
源码如下:
void push_back(_Ty&& _Val)
{ // insert element at end
if (_Inside(_STD addressof(_Val)))
{ // push back an element
size_type _Idx = _STD addressof(_Val) - this->_Myfirst;
if (this->_Mylast == this->_Myend)
_Reserve(1);
_Orphan_range(this->_Mylast, this->_Mylast);
_Cons_val(this->_Alval,
this->_Mylast,
_STD forward<_Ty>(this->_Myfirst[_Idx]));
++this->_Mylast;
}
else
{ // push back a non-element
if (this->_Mylast == this->_Myend)
_Reserve(1);
_Orphan_range(this->_Mylast, this->_Mylast);
_Cons_val(this->_Alval,
this->_Mylast,
_STD forward<_Ty>(_Val));
++this->_Mylast;
}
}
当调用void _Reserve(size_type _Count)函数时,先获取当前的_Size,(使用this->_Mylast - this->_Myfirst得到),判断当前_Capacity是否足以使_Size增长_Count大小。若够,则直接修改_Size,否则调用size_t _Grow_to(size_type _Count)函数将当前_Capacity增加50%。若增长50%会超过max_size()(即_Alval.max_size())或依然小于_Count,则直接将capacity增长至size。
代码如下:
void _Reserve(size_type _Count)
{ // ensure room for _Count new elements, grow exponentially
size_type _Size = size();
if (max_size() - _Count < _Size)
_Xlen();
else if ((_Size += _Count) <= capacity())
;
else
reserve(_Grow_to(_Size));
}
size_type _Grow_to(size_type _Count) const
{ // grow by 50% or at least to _Count
size_type _Capacity = capacity();
_Capacity = max_size() - _Capacity / 2 < _Capacity
? 0 : _Capacity + _Capacity / 2; // try to grow by 50%
if (_Capacity < _Count)
_Capacity = _Count;
return (_Capacity);
}
在进行reserve()时,若需求的空间大小大于最大值,则调用__declspec(noreturn) void _Xlen() const记录一个错误。若大小符合,先用_Ptr指向新申请的_Count大小的内存空间,然后将原有数据全部复制到_Ptr所指向的空间中,逐个调用析构函数,再删除原有空间。最后在函数尾端修改end,first,last的值,使其指向新空间,并满足新空间的大小。
代码如下所示:
void reserve(size_type _Count)
{ // determine new minimum length of allocated storage
if (max_size() < _Count)
_Xlen(); // result too long
else if (capacity() < _Count)
{ // not enough room, reallocate
pointer _Ptr = this->_Alval.allocate(_Count);
_TRY_BEGIN
_Umove(this->_Myfirst, this->_Mylast, _Ptr);
_CATCH_ALL
this->_Alval.deallocate(_Ptr, _Count);
_RERAISE;
_CATCH_END
size_type _Size = size();
if (this->_Myfirst != 0)
{ // destroy and deallocate old array
_Destroy(this->_Myfirst, this->_Mylast);
this->_Alval.deallocate(this->_Myfirst,
this->_Myend - this->_Myfirst);
}
this->_Orphan_all();
this->_Myend = _Ptr + _Count;
this->_Mylast = _Ptr + _Size;
this->_Myfirst = _Ptr;
}
}
__declspec(noreturn) void _Xlen() const { // report a length_error _Xlength_error("vector<T> too long"); }
申请空间的代码如下:
template<class _Ty> inline
_Ty _FARQ *_Allocate(_SIZT _Count, _Ty _FARQ *)
{ // allocate storage for _Count elements of type _Ty
void *_Ptr = 0;
if (_Count <= 0)
_Count = 0;
else if (((_SIZT)(-1) / sizeof (_Ty) < _Count)
|| (_Ptr = ::operator new(_Count * sizeof (_Ty))) == 0)
_THROW_NCEE(bad_alloc, 0);
return ((_Ty _FARQ *)_Ptr);
}
对于下面这条代码,我没看懂……看翻译,貌似是什么“孤儿迭代器”,没搞明白
_Orphan_range(this->_Mylast, this->_Mylast);
接下来是
_Cons_val(this->_Alval, this->_Mylast, _STD forward<_Ty>(_Val));
++this->_Mylast;
意思是将_Val的值存储到this->_Mylast所指向的空间中,并将_Mylast向后指一位。
源码如下:
// TEMPLATE FUNCTIONS _Cons_val AND _Dest_val
template<class _Alloc,
class _Ty1,
class _Ty2>
void _Cons_val(_Alloc& _Alval, _Ty1 *_Pdest, _Ty2&& _Src)
{ // construct using allocator
_Alval.construct(_Pdest, _STD forward<_Ty2>(_Src));
}
所谓的_Ty &&是“右值引用“
vector还有一个功能与void push_back(_Ty&& _Val)类似的函数:
void emplace_back(_Ty&& _Val)
这个函数与void push_back(_Ty&& _Val)的功能类似,均为在vector尾端添加一个元素,但void emplace_back(_Ty&& _Val)相对push_back来 可以避免额外的复制与移动操作。
参见:blog.csdn.net/caroline_wendy/article/details/12967193