vector源码阅读笔记(push_back())

成员变量:

	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



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值