STL中几种常见迭代器的写法以及失效问题

在自主实现STL的过程中,可以看出有的就是指针,有的则可以用类实现。用法大致类似于指针,但在细节会出现差别,这就要从底层谈起。

1.string、vector、list迭代器的实现

string:

string中其实就和指针类似

vector:vector内其实也和指针类似

 

 

list:

// 同一个类模板实例化出的两个类型
	// typedef __list_iterator<T, T&, T*> iterator;
	// typedef __list_iterator<T, const T&, const T*> const_iterator;
	template<class T, class Ref, class Ptr>
	struct __list_iterator
	{
		typedef list_node<T> node;
		typedef __list_iterator<T, Ref, Ptr> Self;
		node* _pnode;//编译器自动生成的析构函数不会处理指针

		__list_iterator(node* p)
			:_pnode(p)
		{}

		
		Ptr operator->()
		{
			return &_pnode->_data;
		}

		// iterator it
		// *it
		// ++it;
		Ref operator*()
		{
			return _pnode->_data;
		}

		// const iterator cit
		// *cit
		// ++cit 这样的话,可以解引用,但是不能++
		/*const T& operator*() const
		{
		return _pnode->_data;
		}*/

		// ++it
		Self& operator++()
		{
			_pnode = _pnode->_next;
			return *this;
		}

		// it++
		Self operator++(int)
		{
			Self tmp(*this);
			_pnode = _pnode->_next;
			return tmp;
		}

		Self& operator--()
		{
			_pnode = _pnode->_prev;
			return *this;
		}

		Self operator--(int)
		{
			Self tmp(*this);
			_pnode = _pnode->_prev;
			return tmp;
		}

		bool operator!=(const Self& it) const
		{
			return _pnode != it._pnode;
		}

		bool operator==(const Self& it) const
		{
			return _pnode == it._pnode;
		}
	};

 2.常见迭代器失效

(1)序列式容器(vector,string)--->insert/erase时失效

这种容器因为会出现扩容问题在insert时,所以会出现迭代器失效(其实也就是指针失效了)

//迭代器失效
		iterator insert(iterator pos, const T& val)//扩容导致pos失效了,需要更新处理一下
		{           //pos不用引用,因为有时会用传值返回,导致数值变化
			//扩容
			if (_finish == _endofstorage)
			{
				size_t len = pos - _start;
				size_t newCapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newCapacity);
				pos = _start + len;
			}
			//挪动数据
			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				end--;
			}
			*pos = val;
			++_finish;
			return pos;
		}
        iterator erase(iterator pos)//我们认为erase结束后pos失效,所以要用返回值来更新迭代器
		{
			assert(pos >= _start&&pos < _finish);
			iterator begin =  pos+1;
			while (begin<_finish)
			{
				*(begin-1) = *(begin);
				begin++;
			}
			_finish--;
			return pos;
		}

但我们可以发现在insert、erase时返回值返回正确迭代器,故我们可以在使用insert、erase后更新迭代器即可以继续使用

(2)关联式迭代器失效(如map, set,multimap,multiset)--->erase时失效

iterator erase(iterator pos)
		{
			assert(pos != end());

			node* prev = pos._pnode->_prev;
			node* next = pos._pnode->_next;

			prev->_next = next;
			next->_prev = prev;

			delete pos._pnode;
			--_size;

			return iterator(next);
		}

在这里我们可以看出,原来pos指向的位置被删除了,只要在函数内将迭代器更新并返回迭代器即可以避免报错。在1.使用完erase后即时将迭代器更新或者在2.使用erase时进行迭代器后置++也可以避免错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值