类结构框架
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调用reserve。size_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