13. 迭代器失效问题、迭代器失效底层原理及实现

在这里插入图片描述
在这里插入图片描述
上述程序很大可能报错!这就叫迭代器失效!(扩容也失效!)

当容器调用erase方法后,当前位置到容器末尾元素所有迭代器全部失效
当容器调用insert方法后,当前位置到容器末尾元素所有迭代器全部失效

迭代器失效后,如何解决?
对插入删除点的迭代器进行更新操作!:
在这里插入图片描述
erase后返回erase元素的下一个元素的迭代器!
在这里插入图片描述
insert后返回的是插入的元素的迭代器

迭代器失效如何实现?

#include <iostream>
using namespace std;

#if 0
// 定义容器的空间配置器,和C++标准库的allocator实现一样
template<typename T>
struct Allocator
{
	T* allocate(size_t size) // 负责内存开辟
	{
		return (T*)malloc(sizeof(T) * size);
	}
	void deallocate(void *p) // 负责内存释放
	{
		free(p);
	}
	void construct(T *p, const T &val) // 负责对象构造
	{
		new (p) T(val); // 定位new
	}
	void destroy(T *p) // 负责对象析构
	{
		p->~T(); // ~T()代表了T类型的析构函数
	}
};

/*
容器底层内存开辟,内存释放,对象构造和析构,都通过allocator空间配置器来实现
*/
template<typename T, typename Alloc = Allocator<T>>
class vector
{
public:
	vector(int size = 10)
	{
		// 需要把内存开辟和对象构造分开处理
		//_first = new T[size];
		_first = _allocator.allocate(size);
		_last = _first;
		_end = _first + size;
	}
	~vector()
	{
		// 析构容器有效的元素,然后释放_first指针指向的堆内存
		// delete[]_first;
		for (T *p = _first; p != _last; ++p)
		{
			_allocator.destroy(p); // 把_first指针指向的数组的有效元素进行析构操作
		}
		_allocator.deallocate(_first); // 释放堆上的数组内存
		_first = _last = _end = nullptr;
	}
	vector(const vector<T> &rhs)
	{
		int size = rhs._end - rhs._first;
		//_first = new T[size];
		_first = _allocator.allocate(size);
		int len = rhs._last - rhs._first;
		for (int i = 0; i < len; ++i)
		{
			//_first[i] = rhs._first[i];
			_allocator.construct(_first + i, rhs._first[i]);
		}
		_last = _first + len;
		_end = _first + size;
	}
	vector<T>& operator=(const vector<T> &rhs)
	{
		if (this == &rhs)
			return *this;

		//delete[]_first;
		for (T *p = _first; p != _last; ++p)
		{
			_allocator.destroy(p); // 把_first指针指向的数组的有效元素进行析构操作
		}
		_allocator.deallocate(_first);

		int size = rhs._end - rhs._first;
		//_first = new T[size];
		_first = _allocator.allocate(size);
		int len = rhs._last - rhs._first;
		for (int i = 0; i < len; ++i)
		{
			//_first[i] = rhs._first[i];
			_allocator.construct(_first + i, rhs._first[i]);
		}
		_last = _first + len;
		_end = _first + size;
		return *this;
	}
	void push_back(const T &val) // 向容器末尾添加元素
	{
		if (full())
			expand();
		//*_last++ = val;   _last指针指向的内存构造一个值为val的对象
		_allocator.construct(_last, val);
		_last++;
	}
	void pop_back() // 从容器末尾删除元素
	{
		if (empty())
			return;
		// erase(it);  verify(it._ptr, _last);
		// insert(it, val); verify(it._ptr, _last);
		verify(_last - 1, _last);
		//--_last; // 不仅要把_last指针--,还需要析构删除的元素
		--_last;
		_allocator.destroy(_last);
	}
	T back()const // 返回容器末尾的元素的值
	{
		return *(_last - 1);
	}
	bool full()const { return _last == _end; }
	bool empty()const { return _first == _last; }
	int size()const { return _last - _first; }
	T& operator[](int index) // vec[2]
	{ 
		if (index < 0 || index >= size())
		{
			throw "OutOfRangeException";
		}
		return _first[index]; 
	}

	// insert erase

	// #1迭代器一般实现成容器的嵌套类型
	class iterator
	{
	public:
		friend class vector<T, Alloc>;
		iterator(vector<T, Alloc> *pvec=nullptr
			, T *ptr = nullptr)
			:_ptr(ptr), _pVec(pvec)
		{
			Iterator_Base *itb = 
				new Iterator_Base(this, _pVec->_head._next);
			_pVec->_head._next = itb;
		}
		bool operator!=(const iterator &it)const
		{
			// 检查迭代器的有效性
			if (_pVec == nullptr || _pVec != it._pVec)
			{
				throw "iterator incompatable!";
			}
			return _ptr != it._ptr;
		}
		void operator++()
		{
			// 检查迭代器的有效性
			if (_pVec == nullptr)
			{
				throw "iterator invalid!";
			}
			_ptr++;
		}
		T& operator*() 
		{ 
			// 检查迭代器的有效性
			if (_pVec == nullptr)
			{
				throw "iterator invalid!";
			}
			return *_ptr; 
		} 
		const T& operator*()const 
		{ 
			// 检查迭代器的有效性
			if (_pVec == nullptr)
			{
				throw "iterator invalid!";
			}
			return *_ptr; 
		}
	private:
		T *_ptr;
		// 当前迭代器迭代器是哪个容器对象
		vector<T, Alloc> *_pVec;
	};
	// 需要给容器提供begin和end方法
	iterator begin() { return iterator(this, _first); }
	iterator end() { return iterator(this, _last); }

	// 检查迭代器失效
	void verify(T *first, T *last)
	{
		Iterator_Base *pre = &this->_head;
		Iterator_Base *it = this->_head._next;
		while (it != nullptr)
		{
			if (it->_cur->_ptr > first && it->_cur->_ptr <= last)
			{
				// 迭代器失效,把iterator持有的容器指针置nullptr
				it->_cur->_pVec = nullptr;
				// 删除当前迭代器节点,继续判断后面的迭代器节点是否失效
				pre->_next = it->_next;
				delete it;
				it = pre->_next;
			}
			else
			{
				pre = it;
				it = it->_next;
			}
		}
	}

	// 自定义vector容器insert方法的实现
	iterator insert(iterator it, const T &val)
	{
		/* 
		1.不考虑扩容 verify(_first - 1, _last);
		2.不考虑it._ptr的指针合法性
		*/
		verify(it._ptr - 1, _last);
		T *p = _last;
		while (p > it._ptr)
		{
			_allocator.construct(p, *(p-1));
			_allocator.destroy(p - 1);
			p--;
		}
		_allocator.construct(p, val);
		_last++;
		return iterator(this, p);
	}

	// 自定义vector容器erase方法的实现
	iterator erase(iterator it)
	{
		verify(it._ptr - 1, _last);
		T *p = it._ptr;
		while (p < _last-1)
		{
			_allocator.destroy(p);
			_allocator.construct(p, *(p + 1));
			p++;
		}
		_allocator.destroy(p);
		_last--;
		return iterator(this, it._ptr);
	}

private:
	T *_first; // 指向数组起始的位置
	T *_last;  // 指向数组中有效元素的后继位置
	T *_end;   // 指向数组空间的后继位置
	Alloc _allocator; // 定义容器的空间配置器对象

	// 容器迭代器失效增加代码
	struct Iterator_Base
	{
		Iterator_Base(iterator *c=nullptr, Iterator_Base *n=nullptr)
			:_cur(c), _next(n) {}
		iterator *_cur;
		Iterator_Base *_next;
	};
	Iterator_Base _head;

	void expand() // 容器的二倍扩容
	{
		int size = _end - _first;
		//T *ptmp = new T[2 * size];
		T *ptmp = _allocator.allocate(2 * size);
		for (int i = 0; i < size; ++i)
		{
			//ptmp[i] = _first[i];
			_allocator.construct(ptmp + i, _first[i]);
		}
		//delete[]_first;
		for (T *p = _first; p != _last; ++p)
		{
			_allocator.destroy(p);
		}
		_allocator.deallocate(_first);
		_first = ptmp;
		_last = _first + size;
		_end = _first + 2 * size;
	}
};

int main()
{
	vector<int> vec(200);
	for (int i = 0; i < 20 ; ++i)
	{
		vec.push_back(rand() % 100 + 1);
	}

	auto it = vec.begin();
	while (it != vec.end())
	{
		if (*it % 2 == 0)
		{
			// 迭代器失效的问题,第一次调用erase以后,迭代器it就失效了
			it = vec.erase(it); // insert(it, val)   erase(it)
		}
		else
		{
			++it;
		}
	}

	for (int v : vec)
	{
		cout << v << " ";
	}
	cout << endl;



#if 0
	auto it1 = vec.end();
	vec.pop_back(); // verify(_last-1, _last)
	auto it2 = vec.end();
	cout << (it1 != it2) << endl;


	int size = vec.size();
	for (int i = 0; i < size; ++i)
	{
		cout << vec[i] << " ";
	}
	cout << endl;

	auto it = vec.begin();
	for (; it != vec.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;

	// foreach
	for (int val : vec) // 其底层原理,就是通过容器的迭代器来实现容器遍历的
	{
		cout << val << " ";
	}
	cout << endl;
#endif
	return 0;
}
#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值