1 vector迭代器失效
1.1 vector迭代器的实现
vector迭代器实现为类指针
class vector : protected _Vector_base<_Tp, _Alloc>
{
// requirements:
__STL_CLASS_REQUIRES(_Tp, _Assignable);
private:
typedef _Vector_base<_Tp, _Alloc> _Base;
public:
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;
1.2 vector执行erase之后,被删除节点之后的迭代器全部失效
erase本质上是将后面的元素拷贝到被删除元素之后的位置上,所以被删除元素之后的元素的指针将发生改变,导致失效
iterator erase(iterator __position) {
if (__position + 1 != end())
// 如果不是最后一个元素,那么把后面的元素往前移动 ---> 将__position + 1到_M_finish的元素拷贝到__position往后的位置
copy(__position + 1, _M_finish, __position);
--_M_finish;
// 删除最后一个元素
destroy(_M_finish);
return __position;
}
iterator erase(iterator __first, iterator __last) {
//将last到_M_finish的元素拷贝到__first及其之后的位置上
iterator __i = copy(__last, _M_finish, __first);
destroy(__i, _M_finish);
_M_finish = _M_finish - (__last - __first);
return __first;
}
1.3 vector执行insert操作后,如果没有扩容,则插入元素之后的所有迭代器失效;如果有扩容则全部失效
可以看到如果容量足够(无需扩容),则操作是将插入位置后的元素整体往后挪动一个位置,也就是插入位置之后的元素地址都会改变;否则,容量不够需要重新申请一块内存,然后将元素拷贝过去,这导致所有元素的地址都会改变。
iterator insert(iterator __position, const _Tp& __x) {
size_type __n = __position - begin();
if (_M_finish != _M_end_of_storage && __position == end()) {
construct(_M_finish, __x);
++_M_finish;
}
else
_M_insert_aux(__position, __x);
return begin() + __n;
}
iterator insert(iterator __position) {
size_type __n = __position - begin();
//如果在末尾插入
if (_M_finish != _M_end_of_storage && __position == end()) {
construct(_M_finish);
++_M_finish;
}
else
_M_insert_aux(__position);
//返回插入元素的迭代器
return begin() + __n;
}
template <class _Tp, class _Alloc>
void
vector<_Tp, _Alloc>::_M_insert_aux(iterator __position)
{
//容器容量足够
if (_M_finish != _M_end_of_storage) {
//_M_finish位置上构造值为*(_M_finish - 1)的元素
construct(_M_finish, *(_M_finish - 1));
++_M_finish;
//将__position到_M_finish - 2的元素拷贝到 _M_finish - 1往前的各位置上
copy_backward(__position, _M_finish - 2, _M_finish - 1);
*__position = _Tp();
}
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);
++__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;
}
}
2 list迭代器失效
2.1 list迭代器实现
可以看到list迭代器实现为模板类_List_iterator
template <class _Tp, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >
class list : protected _List_base<_Tp, _Alloc> {
// requirements:
__STL_CLASS_REQUIRES(_Tp, _Assignable);
typedef _List_base<_Tp, _Alloc> _Base;
protected:
typedef void* _Void_pointer;
public:
typedef _Tp value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef _List_node<_Tp> _Node;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef typename _Base::allocator_type allocator_type;
allocator_type get_allocator() const { return _Base::get_allocator(); }
public:
//迭代器由模板类实现
typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator;
看下_List_iterator的具体实现,可以看到我们得到的迭代器实质是 指向每一个链表节点_List_node_base的指针
template<class _Tp, class _Ref, class _Ptr>
struct _List_iterator : public _List_iterator_base {
typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator;
typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator;
typedef _List_iterator<_Tp,_Ref,_Ptr> _Self;
typedef _Tp value_type;
typedef _Ptr pointer;
typedef _Ref reference;
typedef _List_node<_Tp> _Node;
_List_iterator(_Node* __x) : _List_iterator_base(__x) {}
_List_iterator() {}
_List_iterator(const iterator& __x) : _List_iterator_base(__x._M_node) {}
reference operator*() const { return ((_Node*) _M_node)->_M_data; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
//前置++
_Self& operator++() {
this->_M_incr();
return *this;
}
//后置++
_Self operator++(int) {
_Self __tmp = *this;
this->_M_incr();
return __tmp;
}
//前置--
_Self& operator--() {
this->_M_decr();
return *this;
}
//后置--
_Self operator--(int) {
_Self __tmp = *this;
this->_M_decr();
return __tmp;
}
};
void _M_incr() { _M_node = _M_node->_M_next; }
void _M_decr() { _M_node = _M_node->_M_prev; }
2.2 list执行erase操作后,仅有删除节点的迭代器失效
可以看到只有删除节点的内存被释放了,指向他的指针也就无效了,其他位置元素的地址并无改变
iterator erase(iterator __position) {
_List_node_base* __next_node = __position._M_node->_M_next;
_List_node_base* __prev_node = __position._M_node->_M_prev;
_Node* __n = (_Node*) __position._M_node;
//改变前继节点的后继指针
__prev_node->_M_next = __next_node;
//改变后继节点的前继指针
__next_node->_M_prev = __prev_node;
//释放删除节点的内存
_Destroy(&__n->_M_data);
_M_put_node(__n);
//返回删除节点位置的后继节点迭代器
return iterator((_Node*) __next_node);
}
2.3 list执行insert操作后,所有迭代器不失效
只是改变了插入位置元素的前继指针和其前继元素的后继指针,各个节点的迭代器(地址并无改变)
iterator insert(iterator __position, const _Tp& __x) {
_Node* __tmp = _M_create_node(__x);
__tmp->_M_next = __position._M_node;
__tmp->_M_prev = __position._M_node->_M_prev;
__position._M_node->_M_prev->_M_next = __tmp;
__position._M_node->_M_prev = __tmp;
return __tmp;
}
3 map迭代器失效
3.1 map迭代器实现
可以看到直接被定义为底层数据接口红黑树的迭代器:
template <class _Key, class _Tp, class _Compare, class _Alloc>
class map {
public:
// requirements:
__STL_CLASS_REQUIRES(_Tp, _Assignable);
__STL_CLASS_BINARY_FUNCTION_CHECK(_Compare, bool, _Key, _Key);
// typedefs:
typedef _Key key_type;
typedef _Tp data_type;
typedef _Tp mapped_type;
typedef pair<const _Key, _Tp> value_type;
typedef _Compare key_compare;
class value_compare
: public binary_function<value_type, value_type, bool> {
friend class map<_Key,_Tp,_Compare,_Alloc>;
protected :
_Compare comp;
value_compare(_Compare __c) : comp(__c) {}
public:
bool operator()(const value_type& __x, const value_type& __y) const {
return comp(__x.first, __y.first);
}
};
private:
//底层红黑树类
typedef _Rb_tree<key_type, value_type,
_Select1st<value_type>, key_compare, _Alloc> _Rep_type;
_Rep_type _M_t; // red-black tree representing map
public:
typedef typename _Rep_type::pointer pointer;
typedef typename _Rep_type::const_pointer const_pointer;
typedef typename _Rep_type::reference reference;
typedef typename _Rep_type::const_reference const_reference;
//直接定义为底层数据结构红黑树类的迭代器
typedef typename _Rep_type::iterator iterator;
typedef typename _Rep_type::const_iterator const_iterator;
typedef typename _Rep_type::reverse_iterator reverse_iterator;
typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator;
typedef typename _Rep_type::size_type size_type;
typedef typename _Rep_type::difference_type difference_type;
typedef typename _Rep_type::allocator_type allocator_type;
然后我们看下红黑树类中,关于迭代器的实现:
class _Rb_tree : protected _Rb_tree_base<_Value, _Alloc> {
typedef _Rb_tree_base<_Value, _Alloc> _Base;
protected:
typedef _Rb_tree_node_base* _Base_ptr;
typedef _Rb_tree_node<_Value> _Rb_tree_node;
typedef _Rb_tree_Color_type _Color_type;
...
public:
//红黑树类中迭代器
typedef _Rb_tree_iterator<value_type, reference, pointer> iterator;
typedef _Rb_tree_iterator<value_type, const_reference, const_pointer>
const_iterator;
然后看下该迭代器的实现——模板类_Rb_tree_iterator:
template <class _Value, class _Ref, class _Ptr>
struct _Rb_tree_iterator : public _Rb_tree_base_iterator
{
typedef _Value value_type;
typedef _Ref reference;
typedef _Ptr pointer;
typedef _Rb_tree_iterator<_Value, _Value&, _Value*>
iterator;
typedef _Rb_tree_iterator<_Value, const _Value&, const _Value*>
const_iterator;
typedef _Rb_tree_iterator<_Value, _Ref, _Ptr>
_Self;
typedef _Rb_tree_node<_Value>* _Link_type;
_Rb_tree_iterator() {}
_Rb_tree_iterator(_Link_type __x) { _M_node = __x; }
_Rb_tree_iterator(const iterator& __it) { _M_node = __it._M_node; }
reference operator*() const { return _Link_type(_M_node)->_M_value_field; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
//前置++
_Self& operator++() { _M_increment(); return *this; }
//后置++
_Self operator++(int) {
_Self __tmp = *this;
_M_increment();
return __tmp;
}
//前置--
_Self& operator--() { _M_decrement(); return *this; }
//后置--
_Self operator--(int) {
_Self __tmp = *this;
_M_decrement();
return __tmp;
}
};
3.2 map执行erase操作后,仅有删除节点的迭代器失效
实质是底层红黑树执行erase操作
void erase(iterator __position) { _M_t.erase(__position); }
size_type erase(const key_type& __x) { return _M_t.erase(__x); }
void erase(iterator __first, iterator __last)
{ _M_t.erase(__first, __last); }
稍微了解红黑删除节点过程的可以知道,删除过程只会修改删除节点的相关的左右子树指针,而不会改变其他节点的地址,所以除了被销毁的删除节点外,其他节点的迭代器不会失效。
3.3 map执行erase操作后,仅有删除节点的迭代器失效
实质也是底层红黑树执行insert操作,所有节点迭代器都不会失效,因为节点本身的地址没有改变,改变的只是其成员——指向左右子树的指针的值。
pair<iterator,bool> insert(const value_type& __x)
{ return _M_t.insert_unique(__x); }
iterator insert(iterator position, const value_type& __x)
{ return _M_t.insert_unique(position, __x); }
#ifdef __STL_MEMBER_TEMPLATES
template <class _InputIterator>
void insert(_InputIterator __first, _InputIterator __last) {
_M_t.insert_unique(__first, __last);
}
#else
void insert(const value_type* __first, const value_type* __last) {
_M_t.insert_unique(__first, __last);
}
void insert(const_iterator __first, const_iterator __last) {
_M_t.insert_unique(__first, __last);
}