VS 2010 STL vector源码分析

类结构框架

vector继承于_Vector_val,继承于_Container_base,_Container_base在debug模式下(只探索debug模式)就是如此定义:typedef _Container_base12 _Container_base;这里面最重要的就是定义了一个叫做“容器代理”的成员变量_Container_proxy *_Myproxy;这个“代理”,就是在container与iterator之间代理一下下。

		// CLASS _Container_proxy
struct _Container_proxy
	{	// store head of iterator chain and back pointer
	_Container_proxy()
		: _Mycont(0), _Myfirstiter(0)
		{	// construct from pointers
		}

	const _Container_base12 *_Mycont;//指向容器,这里其实指向我们的vector
	_Iterator_base12 *_Myfirstiter;  //指向第一个迭代器
	};

所以我们先来看_Container_base12。 

struct _CRTIMP2_PURE _Container_base12
	{	// store pointer to _Container_proxy
public:
	_Container_base12()
		: _Myproxy(0)
		{	// construct childless container
		}

	_Container_base12(const _Container_base12&)
		: _Myproxy(0)
		{	// copy a container
		}

	_Container_base12& operator=(const _Container_base12&)
		{	// assign a container
		return (*this);
		}

	~_Container_base12()
		{	// destroy the container
		_Orphan_all();
		}

	_Iterator_base12 **_Getpfirst() const
		{	// get address of iterator chain
		return (_Myproxy == 0 ? 0 : &_Myproxy->_Myfirstiter);
		}

	void _Orphan_all()	// orphan all iterators
	{	// orphan all iterators
 #if _ITERATOR_DEBUG_LEVEL == 2
	if (_Myproxy != 0)
		{	// proxy allocated, drain it
		_Lockit _Lock(_LOCK_DEBUG);
    
        //下面两步就是把自己(container)与所有的和自己相关的iterator断绝关系
		for (_Iterator_base12 **_Pnext = &_Myproxy->_Myfirstiter;
			*_Pnext != 0; *_Pnext = (*_Pnext)->_Mynextiter)
			(*_Pnext)->_Myproxy = 0;//1,把所有的iterator的proxy置0
		_Myproxy->_Myfirstiter = 0;//2,把链表中第一个迭代器指针置0
		}
 #endif /* _ITERATOR_DEBUG_LEVEL == 2 */
	}
	void _Swap_all(_Container_base12&);	// swap all iterators

	_Container_proxy *_Myproxy;
	};

_Vector_val类里面最重要的是几个变量,看注释应该很容易理解。比如一个vector分配了十个int大小内存,但是只有前三个赋了值,那么_Myfirst指向第0号元素,_Mylast指向3号元素,_Myend指向10号元素(其实不存在此元素)。_Alval是内存分配器,反正大致就是替换new的意思。

		// TEMPLATE CLASS _Vector_val
template<class _Ty,
	class _Alloc>
	class _Vector_val
		: public _Container_base
	{	// base class for vector to hold data
public:
	typedef typename _Alloc::template rebind<_Ty>::other _Alty;
	typedef typename _Alty::size_type size_type;
	typedef typename _Alty::difference_type difference_type;
	typedef typename _Alty::pointer pointer;
	typedef typename _Alty::const_pointer const_pointer;
	typedef typename _Alty::reference reference;
	typedef typename _Alty::const_reference const_reference;
	typedef typename _Alty::value_type value_type;

	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
	};

 

		// TEMPLATE CLASS vector
template<class _Ty,
	class _Ax = allocator<_Ty> >
	class vector
		: public _Vector_val<_Ty, _Ax>
	{	// varying size array of values
public:
	typedef vector<_Ty, _Ax> _Myt;
	typedef _Vector_val<_Ty, _Ax> _Mybase;
	typedef typename _Mybase::_Alty _Alloc;

	typedef _Alloc allocator_type;
	typedef typename _Alloc::size_type size_type;
	typedef typename _Alloc::difference_type difference_type;
	typedef typename _Alloc::pointer pointer;
	typedef typename _Alloc::const_pointer const_pointer;
	typedef typename _Alloc::reference reference;
	typedef typename _Alloc::const_reference const_reference;
	typedef typename _Alloc::value_type value_type;

 #define _VICONT(it)	it._Getcont()
 #define _VIPTR(it)	(it)._Ptr

	typedef _Vector_iterator<_Mybase> iterator;
	typedef _Vector_const_iterator<_Mybase> const_iterator;

	typedef _STD reverse_iterator<iterator> reverse_iterator;
	typedef _STD reverse_iterator<const_iterator> const_reverse_iterator;
}

在xmemory文件中有这也一行代码: #define _ALLOCATOR    allocator,所以我们用到的内存分配器就是_ALLOCATOR。话说为啥不直接用_ALLOCATOR呢,"_"开头的命名方式,是代表此乃 “内部”的。可能和此相关。 

从vector的构造说起

std::vector<int> vecInt;
	vector()
		: _Mybase()
		{	// construct empty vector
		}
	_Vector_val(_Alloc _Al = _Alloc())
		: _Alval(_Al)
		{	// construct allocator from _Al
        //定义了一个_Container_proxy类型的分配器
		typename _Alloc::template rebind<_Container_proxy>::other
			_Alproxy(_Alval);
        //这面这几行代码无非相当于:_Myproxy = new _Container_proxy();
		this->_Myproxy = _Alproxy.allocate(1);
		_Cons_val(_Alproxy, this->_Myproxy, _Container_proxy());
		this->_Myproxy->_Mycont = this;

        //初始化三个超重要的成员
		_Myfirst = 0;
		_Mylast = 0;
		_Myend = 0;
		}

从push_back查看内部实现细节

	vecInt.push_back(1);
	void push_back(_Ty&& _Val)
		{	// insert element at end
        //如果_Val的地址在this->_Mylast 和this->_Myfirst中间
		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);
            //和else块里相比,这里用_Myfirst[_Idx]赋值
			_Cons_val(this->_Alval,
				this->_Mylast,
				_STD forward<_Ty>(this->_Myfirst[_Idx]));
			++this->_Mylast;
			}
		else
			{	// push back a non-element
            //如果没有空间了就需要扩容了,capacity就要变大了
			if (this->_Mylast == this->_Myend)
				_Reserve(1);//延伸1,扩容一个元素
			_Orphan_range(this->_Mylast, this->_Mylast);
            //把_Val赋值到最后_Mylast位置,并把_Mylast向后移动一位
			_Cons_val(this->_Alval,
				this->_Mylast,
				_STD forward<_Ty>(_Val));
			++this->_Mylast;
			}
		}

 从上面的延伸1看一下扩容的事情

	void _Reserve(size_type _Count)
		{	// ensure room for _Count new elements, grow exponentially
		size_type _Size = size();
        //假若扩容_Count之后,超过max_size(),就要报错了
		if (max_size() - _Count < _Size)
			_Xlen();
        //要是不需要扩容,do nothing;其实这时候也不需要调用_Reserve此函数啦
		else if ((_Size += _Count) <= capacity())
			;
		else
			reserve(_Grow_to(_Size));
		}

_Reserve调用reservesize_type _Grow_to(size_type _Count) const

	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%
        //这个函数返回capacity()*1.5与_Count之间大者
		if (_Capacity < _Count)
			_Capacity = _Count;
		return (_Capacity);
		}
	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
            //1,重新分配内存
			pointer _Ptr = this->_Alval.allocate(_Count);

			_TRY_BEGIN
            //2,把之前内存里的内容拷贝过来
			_Umove(this->_Myfirst, this->_Mylast, _Ptr);
			_CATCH_ALL
            //3,删除之前内存(catch到的情况)
			this->_Alval.deallocate(_Ptr, _Count);
			_RERAISE;
			_CATCH_END

			size_type _Size = size();
			if (this->_Myfirst != 0)
				{	// destroy and deallocate old array
                //4,析构这些对象,要是int类型的就谈不上析构了
				_Destroy(this->_Myfirst, this->_Mylast);
                //3,删除之前内存(未catch到的情况)
				this->_Alval.deallocate(this->_Myfirst,
					this->_Myend - this->_Myfirst);
				}
            //5,_Orphan_all()就是把所有iteraotor的_Myproxy置为0,并 _Myproxy->_Myfirstiter = 0;
			this->_Orphan_all();
            //6,重新给位置变量赋值
			this->_Myend = _Ptr + _Count;//指向的这个对象不存在的
			this->_Mylast = _Ptr + _Size;//指向真正最后一个元素后面那个元素
			this->_Myfirst = _Ptr;//永远指向0号元素
			}
		}

迭代器

struct _Iterator_base12
	{	// store links to container proxy, next iterator
public:
	_Iterator_base12()
		: _Myproxy(0), _Mynextiter(0)
		{	// construct orphaned iterator
		}

	_Iterator_base12(const _Iterator_base12& _Right)
		: _Myproxy(0), _Mynextiter(0)
		{	// copy an iterator
		*this = _Right;
		}

	_Iterator_base12& operator=(const _Iterator_base12& _Right)
		{	// assign an iterator
		if (_Myproxy != _Right._Myproxy)
			_Adopt(_Right._Myproxy->_Mycont);
		return (*this);
		}

	~_Iterator_base12()
		{	// destroy the iterator
 #if _ITERATOR_DEBUG_LEVEL == 2
		_Lockit _Lock(_LOCK_DEBUG);
		_Orphan_me();
 #endif /* _ITERATOR_DEBUG_LEVEL == 2 */
		}

    //_Adopt的作用就是把参数iterator放到iterator单向链表的头部
	void _Adopt(const _Container_base12 *_Parent)
		{	// adopt this iterator by parent
		if (_Parent != 0)
			{	// have a parent, do adoption
			_Container_proxy *_Parent_proxy = _Parent->_Myproxy;

 #if _ITERATOR_DEBUG_LEVEL == 2
			if (_Myproxy != _Parent_proxy)
				{	// change parentage
				_Lockit _Lock(_LOCK_DEBUG);
                //把自己和之前的container切除关系
				_Orphan_me();
                //下面三行代码把自己放入链表头部
				_Mynextiter = _Parent_proxy->_Myfirstiter;
				_Parent_proxy->_Myfirstiter = this;
                 //自己proxy与container的proxy同步
				_Myproxy = _Parent_proxy;
				}
 #else /* _ITERATOR_DEBUG_LEVEL == 2 */
            //自己proxy与container的proxy同步
			_Myproxy = _Parent_proxy;
 #endif /* _ITERATOR_DEBUG_LEVEL == 2 */
			}
		}

	void _Clrcont()
		{	// disown owning container
		_Myproxy = 0;
		}

	const _Container_base12 *_Getcont() const
		{	// get owning container
		return (_Myproxy == 0 ? 0 : _Myproxy->_Mycont);
		}

	_Iterator_base12 **_Getpnext()
		{	// get address of remaining iterator chain
		return (&_Mynextiter);
		}
    
    //把自己孤立出去:remove self from list
	void _Orphan_me()
		{	// cut ties with parent
 #if _ITERATOR_DEBUG_LEVEL == 2
		if (_Myproxy != 0)
			{	// adopted, remove self from list
			_Iterator_base12 **_Pnext = &_Myproxy->_Myfirstiter;
            //where循环找到自己
			while (*_Pnext != 0 && *_Pnext != this)
				_Pnext = &(*_Pnext)->_Mynextiter;

            //这句代码的意思其实就是把自己从iterator单向链表中除去啊,好好想想是不是这样。
			*_Pnext = _Mynextiter;
            //代理置0后,就不能用代理里面保存的container了,就和container(vector)切断关系了
			_Myproxy = 0;
			}
 #endif /* _ITERATOR_DEBUG_LEVEL == 2 */
		}

	_Container_proxy *_Myproxy;
	_Iterator_base12 *_Mynextiter;//会把同一个vector的iterator放入一个单向链表中,此用来指向下一个iterator
	};
template<class _Category,
	class _Ty,
	class _Diff,
	class _Pointer,
	class _Reference,
	class _Base>
	struct _Iterator012//这个前置声明放在这很风骚
		: public _Base//对于vector的迭代器,此_Base就是_Iterator_base12
	typedef _Category iterator_category;
	typedef _Ty value_type;
	typedef _Diff difference_type;
	typedef _Diff distance_type;	// retained
	typedef _Pointer pointer;
	typedef _Reference reference;
	};

 迭代器里面最重要的就是指向储存对象类型的成员变量指针。然后根据这个指针做一系列操作,使iterator和pointer行为类似。

//xutility文件
typedef _Iterator_base12 _Iterator_base;
		// TEMPLATE CLASS _Vector_const_iterator
template<class _Myvec>
	class _Vector_const_iterator
		: public _Iterator012<random_access_iterator_tag,//随机访问型tag
			typename _Myvec::value_type,
			typename _Myvec::difference_type,
			typename _Myvec::const_pointer,
			typename _Myvec::const_reference,
            //_Iterator_base即为_Iterator_base12,_Iterator_base会成为 _Vector_const_iterator的基类
			_Iterator_base>
	{	// iterator for nonmutable vector
public:
	typedef _Vector_const_iterator<_Myvec> _Myiter;
	typedef random_access_iterator_tag iterator_category;

	typedef typename _Myvec::pointer _Tptr;
	typedef typename _Myvec::value_type value_type;
	typedef typename _Myvec::difference_type difference_type;
	typedef typename _Myvec::const_pointer pointer;
	typedef typename _Myvec::const_reference reference;

    typedef pointer _Unchecked_type;
	//把一个pointer 类指针赋给我们的_Ptr
    _Myiter& _Rechecked(_Unchecked_type _Right)
		{	// reset from unchecked iterator
		this->_Ptr = (_Tptr)_Right;
		return (*this);
		}

    //返回真正的_Ptr
	_Unchecked_type _Unchecked() const
		{	// make an unchecked iterator
		return (_Unchecked_type(this->_Ptr));
		}

	reference operator*() const
		{	// return designated object        
        //返回真正的_Ptr所指向的东西,所以有 (*iter).成员变量/成员函数操作
		return (*this->_Ptr);
		}

	pointer operator->() const
		{	// return pointer to class object
        //*this返回此iterator,在加*返回_Ptr所指向的东西,再取地址。
        //所以有iter->成员变量/成员函数操作
        //这里直接返回_Ptr可行否?
		return (&**this);
		}

    //这里拿重载++操作举例,其实操作全是在_Ptr指针上,++后iterator并没变,变的是指针。
	_Myiter& operator++()
		{	// preincrement
 #if _ITERATOR_DEBUG_LEVEL == 2
		if (this->_Getcont() == 0
			|| this->_Ptr == 0
			|| ((_Myvec *)this->_Getcont())->_Mylast <= this->_Ptr)
			{	// report error
			_DEBUG_ERROR("vector iterator not incrementable");
			_SCL_SECURE_OUT_OF_RANGE;
			}

 #elif _ITERATOR_DEBUG_LEVEL == 1
		_SCL_SECURE_VALIDATE(this->_Getcont() != 0);
		_SCL_SECURE_VALIDATE_RANGE(
			this->_Ptr != 0
			&& this->_Ptr < ((_Myvec *)this->_Getcont())->_Mylast);
 #endif /* _ITERATOR_DEBUG_LEVEL */

		++this->_Ptr;
		return (*this);
		}
    
    _Tptr _Ptr;	// pointer to element in vector
	};
		// TEMPLATE CLASS _Vector_iterator
template<class _Myvec>
	class _Vector_iterator
		: public _Vector_const_iterator<_Myvec>
	{	// iterator for mutable vector
public:
	typedef _Vector_iterator<_Myvec> _Myiter;
	typedef _Vector_const_iterator<_Myvec> _Mybase;
	typedef random_access_iterator_tag iterator_category;

	typedef typename _Myvec::value_type value_type;
	typedef typename _Myvec::difference_type difference_type;
	typedef typename _Myvec::pointer pointer;
	typedef typename _Myvec::reference reference;
    }

 vector与iterator关联

我们用到iterator最常用的就是下面这样代码了吧。

vector<int>::iterator iter = vecInt.begin();

begin()返回一个iterator 

//vector的成员函数	
iterator begin()
{	// return iterator for beginning of mutable sequence
	return (iterator(this->_Myfirst, this));
}

_Mybase就是_Vector_const_iterator

//iterator构造函数	
_Vector_iterator(pointer _Parg, const _Container_base *_Pvector)
		: _Mybase(_Parg, _Pvector)
		{	// construct with pointer _Parg
		}

下面这个构造函数功能无非就是把_Ptr指向我们vector的元素,把 这个iterator和vector关联起来(靠proxy),并把这个iterator加入到和此vector相关的迭代器链表中。

//_Vector_const_iterator构造函数
_Vector_const_iterator(_Tptr _Parg, const _Container_base *_Pvector)
: _Ptr(_Parg)
{	// construct with pointer _Parg
	this->_Adopt(_Pvector);
}

 几句话再讲一下这个代理。container有一个proxy指针,iterator也有一个proxy指针,都指向proxy。这个proxy是在_Vector_val构造函数里创建的。proxy有两个指针,一个指向container,一个指向迭代器链表第一个iterator。

删除

删除原理

	iterator erase(const_iterator _Where)
		{	// erase element at where
		if (_VICONT(_Where) != this
			|| _VIPTR(_Where) < this->_Myfirst
			|| this->_Mylast <= _VIPTR(_Where))
			_DEBUG_ERROR("vector erase iterator outside range");
        //把where后面元素向前移动一位
		_Move(_VIPTR(_Where) + 1, this->_Mylast, _VIPTR(_Where));
        //移动之后,把最后一个元素析构
		_Destroy(this->_Mylast - 1, this->_Mylast);
        //从_Where到_Mylast把迭代器proxy置0,所以假若有指向后面元素的迭代器,那些迭代器便不能用了
		_Orphan_range(_VIPTR(_Where), this->_Mylast);
        //少了一个元素,_Mylast减一
		--this->_Mylast;
        //依旧返回_Where,不过_Where指向的内容已经发生变化,是未删除之前_Where后面的那个元素了
		return (_Make_iter(_Where));
		}

假若有如下几行代码

	std::vector<int> vecInt;
	vecInt.push_back(1);
	vecInt.push_back(2);
	vecInt.push_back(3);
	std::vector<int>::iterator iter1 = vecInt.begin()+1;
	std::vector<int>::iterator iter2 = vecInt.begin()+1;
	vecInt.erase(iter1);
	*iter2;

运行之后会有“Debug Assertion Failed”的弹框报错。原因就在删除iter1之后,iter2的proxy已经置0。在_Vector_const_iterator的operator *函数中有如下代码片段,this->_Getcont()要用到迭代器的proxy,若为空container返回空,“vector iterator not dereferencable”这句话,编程者经常看到,却不知其意。

	reference operator*() const
		{	// return designated object
 #if _ITERATOR_DEBUG_LEVEL == 2
		if (this->_Getcont() == 0
			|| this->_Ptr == 0
			|| this->_Ptr < ((_Myvec *)this->_Getcont())->_Myfirst
			|| ((_Myvec *)this->_Getcont())->_Mylast <= this->_Ptr)
			{	// report error
			_DEBUG_ERROR("vector iterator not dereferencable");
			_SCL_SECURE_OUT_OF_RANGE;
			}
 #endif /* _ITERATOR_DEBUG_LEVEL */
}

循环删除特定元素 

下面的代码是错误的,就是因为删除之后,iter的proxy已经置0,在迭代器里面_Getcont()返回0就会弹框报错。

	std::vector<int> nVec;
	for(int i = 0; i < 5; ++i)
	nVec.push_back(i);

	std::vector<int>::iterator iter = nVec.begin();
	for(; iter != nVec.end(); ++iter)
	{
		if(*iter == 1)
		nVec.erase(iter);
	}

正确代码方式

std::vector<int>::iterator iter = nVec.begin();
for(; iter != nVec.end();)
{
  if(*iter == 1)
    iter = nVec.erase(iter);
  else
    iter++;
}

 

其他一些重要函数

	void _Orphan_range(pointer _First, pointer _Last) const
	{	// orphan iterators within specified (inclusive) range
		_Lockit _Lock(_LOCK_DEBUG);
		const_iterator **_Pnext = (const_iterator **)this->_Getpfirst();
		if (_Pnext != 0)
		{
			while (*_Pnext != 0)
			{
                //没在_First与_Last范围之内,只做返回下一个iterator的操作
				if ((*_Pnext)->_Ptr < _First || _Last < (*_Pnext)->_Ptr)
					_Pnext = (const_iterator **)(*_Pnext)->_Getpnext();
                //在范围之内
				else
				{	// orphan the iterator
					(*_Pnext)->_Clrcont();//proxy置0
					*_Pnext = *(const_iterator **)(*_Pnext)->_Getpnext();
				}
			}
		}
	}
	//交换两个vector中的内容
	void swap(_Myt& _Right)
		{	// exchange contents with _Right
		if (this == &_Right)
			;	// same object, do nothing
		else if (this->_Alval == _Right._Alval)
			{	// same allocator, swap control information
			this->_Swap_all(_Right);
			_STD swap(this->_Myfirst, _Right._Myfirst);
			_STD swap(this->_Mylast, _Right._Mylast);
			_STD swap(this->_Myend, _Right._Myend);
			}
		else
			{	// different allocator, do multiple assigns
			_Myt _Ts = _Move(*this);

			*this = _Move(_Right);
			_Right = _Move(_Ts);
			}
		}

11

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值