迭代器失效之原理分析

2021-08-20 02:22:21 字數 4532 閱讀 4659

vector迭代器實現為類指標

class vector : protected _vector_base<_tp, _alloc> 

iterator erase(iterator __first, iterator __last)

可以看到如果容量足夠(無需擴容),則操作是將插入位置後的元素整體往後挪動乙個位置,也就是插入位置之後的元素位址都會改變;否則,容量不夠需要重新申請一塊記憶體,然後將元素拷貝過去,這導致所有元素的位址都會改變。

iterator insert(iterator __position, const _tp& __x) 

else

_m_insert_aux(__position, __x);

return begin() + __n;

} iterator insert(iterator __position)

else

_m_insert_aux(__position);

//返回插入元素的迭代器

return begin() + __n;

}template void

vector<_tp, _alloc>::_m_insert_aux(iterator __position)

else

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

}}

可以看到list迭代器實現為模板類_list_iterator

template class list : protected _list_base<_tp, _alloc> 

public:

//迭代器由模板類實現

typedef _list_iterator<_tp,_tp&,_tp*> iterator;

看下_list_iterator的具體實現,可以看到我們得到的迭代器實質是 指向每乙個鍊錶節點_list_node_base的指標

templatestruct _list_iterator : public _list_iterator_base 

_list_iterator() {}

_list_iterator(const iterator& __x) : _list_iterator_base(__x._m_node) {}

reference operator*() const

#ifndef __sgi_stl_no_arrow_operator

pointer operator->() const

#endif /* __sgi_stl_no_arrow_operator */

//前置++

_self& operator++()

//後置++

_self operator++(int)

//前置--

_self& operator--()

//後置--

_self operator--(int)

}; void _m_incr()

void _m_decr()

可以看到只有刪除節點的記憶體被釋放了,指向他的指標也就無效了,其他位置元素的位址並無改變

iterator erase(iterator __position)
只是改變了插入位置元素的前繼指標和其前繼元素的後繼指標,各個節點的迭代器(位址並無改變)

iterator insert(iterator __position, const _tp& __x)
可以看到直接被定義為底層資料介面紅黑樹的迭代器:

template class map 

public:

bool operator()(const value_type& __x, const value_type& __y) const

};private:

//底層紅黑樹類

typedef _rb_tree, 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> 

_rb_tree_iterator(_link_type __x)

_rb_tree_iterator(const iterator& __it)

reference operator*() const

#ifndef __sgi_stl_no_arrow_operator

pointer operator->() const

#endif /* __sgi_stl_no_arrow_operator */

//前置++

_self& operator++()

//後置++

_self operator++(int)

//前置--

_self& operator--()

//後置--

_self operator--(int)

};

實質是底層紅黑樹執行erase操作

void erase(iterator __position) 

size_type erase(const key_type& __x)

void erase(iterator __first, iterator __last)

稍微了解紅黑刪除節點過程的可以知道,刪除過程只會修改刪除節點的相關的左右子樹指標,而不會改變其他節點的位址,所以除了被銷毀的刪除節點外,其他節點的迭代器不會失效。

實質也是底層紅黑樹執行insert操作,所有節點迭代器都不會失效,因為節點本身的位址沒有改變,改變的只是其成員——指向左右子樹的指標的值。

pairinsert(const value_type& __x) 

iterator insert(iterator position, const value_type& __x)

#ifdef __stl_member_templates

template void insert(_inputiterator __first, _inputiterator __last)

#else

void insert(const value_type* __first, const value_type* __last)

void insert(const_iterator __first, const_iterator __last)

C STL之迭代器介紹 原理 失效

今天抽空來看看c 標準庫中迭代器的相關知識。我們知道,stl標準庫一共有六大部件 分配器 容器 迭代器 演算法 仿函式 介面卡。其中,迭代器就是用來 聯結 演算法 仿函式與容器的紐帶。除此之外,在設計模式中有一種模式叫迭代器模式,簡單來說就是提供一種方法,在不需要暴露某個容器的內部表現形式情況下,使...

迭代器失效小分析

stl中容器按儲存方式分為兩類 一是按陣列容器順序儲存的序列式容器 如 vector,deque 另一類是以不連續的節點形式儲存的容器 list set map 迭代器失效小例項 void printvector vector v cout endl void testvector 迭代器失效 對於...

STL之迭代器失效

所謂迭代器失效,是指迭代器已經不是指向原來的位置,這總是出現在需要連續儲存的容器中,如 vector,deque,string。拿vector來說,當需要插入或者刪除元素時,如果原來的容量 capacity 不足以滿足插入的需求,則必須重新分配一塊記憶體,然後將vector物件中所有元素都搬新家,這...