list迭代器的失效问题(对比vector迭代器),list类的实现

list iterator的使用

可以将迭代器理解成一个指针,该指针指向list中的某个节点

函数声明 接口说明
begin+end 返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器
rbegin+rend 返回第一个元素的reverse_iterator,即end位置,返回最后一个元素下一个位置的 reverse_iterator,即begin位置

1. begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动
2. rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动

list的迭代器失效(重点)

将迭代器可以暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。
与vector迭代器失效对比:

  • vector中:在插入元素时,要给所有的迭代器重新赋值,因为插入 元素有可能会导致重新扩容,致使原来迭代器失效,删 除时,当前迭代器需要重新赋值否则会失效。
  • list中:插入元素不会导致迭代器失效, 删除元素时,只会导致当前迭代 器失效,其他迭代器不受影响。
void TestListIterator1() 
{    
	int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };    
	list l(array, array+sizeof(array)/sizeof(array[0]));
 
    auto it = l.begin();    
    while (it != l.end())    
    {        
    	// erase()函数执行后,it所指向的节点已被删除,因此it无效,在下一次使用it时,必须先给其赋 值        
    	l.erase(it);          
    	++it;    
    } 
}
 
// 改正 
void TestListIterator() 
{    
	int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };    
	list l(array, array+sizeof(array)/sizeof(array[0]));
  	auto it = l.begin();    
  	while (it != l.end())    
  	{        
  		l.erase(it++);    // it = l.erase(it);    
  	} 
}

list与vector的对比

vector list
底层结构 动态顺序表,一段连续空间 带头结点的双向循环链表
随机访问 支持随机访问,访问某个元素效率O(1) 不支持随机访问,访问某个元素 效率O(N)
插入和删除 任意位置插入和删除效率低,需要搬移元素,时间复杂 度为O(N),插入时有可能需要增容,增容:开辟新空 间,拷贝元素,释放旧空间,导致效率更低 任意位置插入和删除效率高,不 需要搬移元素,时间复杂度为 O(1)
安全利用率 底层为连续空间,不容易造成内存碎片,空间利用率 高,缓存利用率高 底层节点动态开辟,小节点容易 造成内存碎片,空间利用率低, 缓存利用率低
迭代器 原生态指针 对原生态指针(节点指针)进行封装
迭代失效 在插入元素时,要给所有的迭代器重新赋值,因为插入 元素有可能会导致重新扩容,致使原来迭代器失效,删 除时,当前迭代器需要重新赋值否则会失效 插入元素不会导致迭代器失效, 删除元素时,只会导致当前迭代 器失效,其他迭代器不受影响
使用场景 需要高效存储,支持随机访问,不关心插入删除效率 大量插入和删除操作,不关心随 机访问

list的自实现

	template<class T>
	struct Node
	{
		Node(const T& data = T())
			:_pNext(nullptr)
			, _pPre(nullptr)
			, _data(data)
		{}
		T _data;
		Node<T> *_pNext;
		Node<T> *_pPre;
	};

	template<class T>
	class list_iterator
	{
		typedef Node<T> Node;
		typedef list_iterator<T> shef;
	public:
		list_iterator(Node *ptr)
			:_ptr(ptr)
		{}
		T& operator *()
		{
			return _ptr->_data;
		}
		T* operator ->()
		{
			return &(_ptr->_data);
		}
		shef& operator ++()
		{
			_ptr = _ptr->_pNext;
			return *this;
		}
		shef operator ++(T)
		{
			shef tmp(*this);
			//shef tmp(_ptr);
			_ptr = _ptr->_pNext;
			return tmp;
		}
		shef& operator --()
		{
			_ptr = _ptr->_pPre;
			return *this;
		}
		shef operator --(T)
		{
			shef tmp(_ptr);
			_ptr = _ptr->_pPre;
			return tmp;
		}
		bool operator !=(const shef& it)
		{
			return _ptr != it._ptr;
		}
		bool operator ==(const shef& it)
		{
			return _ptr == it._ptr;
		}
		Node* _ptr;
	};

	template<class iterator, class T>
	struct list_riterator
	{
		typedef Node<T> Node;
		typedef list_riterator<iterator, T> shef;
		list_riterator(Node *ptr)
			:_it(ptr)
		{}
		/*list_riterator(iterator it)
			:_it(it)
		{}*/
		T& operator *()
		{
			auto it = _it;
			--it;
			return *it;
		}
		T* operator ->()
		{
			return &(operator *());
		}
		shef& operator ++()
		{
			--_it;
			return *this;
		}
		shef operator ++(T)
		{
			shef tmp(_it._ptr);
			--_it;
			return tmp;
		}
		shef& operator --()
		{
			++_it;
			return *this;
		}
		shef operator --(T)
		{
			shef tmp(_it._ptr);
			++_it;
			return tmp;
		}
		bool operator !=(shef ptr)
		{
			return _it != ptr._it;
		}
		bool operator ==(shef ptr)
		{
			return _it == ptr._it;
		}
		iterator _it;
	};

	template<class T>
	class list
	{
		typedef Node<T> Node;
		typedef list_iterator<T> iterator;
		typedef const list_iterator<T> const_iterator;
		typedef list_riterator<iterator, T> riterator;
	public:
		list()
		{
			CreateHead();
		}
		list(int n, const T& data)
		{
			CreateHead();
			for (int i = 0; i < n; i++)
				push_back(data);
		}
		template<class Iterator>
		list(Iterator first, Iterator last)
		{
			CreateHead();
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}
		list(const list<T>& L)
		{
			CreateHead();
			/*Node *pt = L._pHead->_pNext;
			while (pt != L._pHead)
			{
				push_back(pt->_data);
				pt = pt->_pNext;
			}*/
			iterator it = L.begin();
			while (it != L.end())
			{
				push_back(*it);
				++it;
			}
		}
		list<T>& operator=(const list<T>& L)
		{
			if (this != &L)
			{
				clear();
				auto it = L.begin();
				while (it != L.end())
				{
					push_back(*it);
					++it;
				}
			}
			return *this;
		}
		~list()
		{
			clear();
			delete _pHead;
		}
		iterator begin()
		{
			return iterator(_pHead->_pNext);
		}
		iterator begin()const 
		{
			return iterator(_pHead->_pNext);
		}
		iterator end()
		{
			return iterator(_pHead);
		}
		iterator end()const 
		{
			return iterator(_pHead);
		}
		riterator rbegin()
		{
			return riterator(_pHead);
		}
		riterator rend()
		{
			return riterator(_pHead->_pNext);
		}
		size_t size()const
		{
			size_t count = 0;
			auto it = begin();
			while (it != end())
			{
				++it;
				++count;
			}
			return count;
		}
		bool empty()const 
		{
			return _pHead->_pNext == _pHead;
		}
		void resize(int n, const T& data = T())
		{
			int oldsize = size();
			if (n > oldsize)
			{
				for (int i = oldsize; i < n; i++)
					push_back(data);
			}
			else
			{
				for (int i = n; i < oldsize; i++)
					pop_back();
			}
		}
		T& front()
		{
			return _pHead->_pNext->_data;
		}
		const T& front()const
		{
			return _pHead->_pNext->_data;
		}
		T& back()
		{
			return _pHead->_pPre->_data;
		}
		const T& back()const
		{
			return _pHead->_pPre->_data;
		}
		void push_back(const T& data)
		{
			insert(end(), data);
		}
		void clear()
		{
			Node* it = _pHead->_pNext;
			while (it != _pHead)
			{
				_pHead->_pNext = it->_pNext;
				delete it;
				it = _pHead->_pNext;
			}
			_pHead->_pNext = _pHead;
			_pHead->_pPre = _pHead;
		}
		void pop_back()
		{
			erase(--end());
		}
		iterator insert(iterator pos, const T& data)
		{
			Node *node = pos._ptr;
			Node *pt = new Node(data);
			pt->_pPre = node->_pPre;
			pt->_pNext = node;
			node->_pPre = pt;
			pt->_pPre->_pNext = pt;
			return iterator(pt);
		}
		iterator erase(iterator pos)
		{
			Node *pt = pos._ptr;
			if (pt == _pHead)
				return end();
			Node *ret = pt->_pNext;
			pt->_pPre->_pNext = pt->_pNext;
			pt->_pNext->_pPre = pt->_pPre;
			delete pt;
			return iterator(ret);
		}
		void push_front(const T& data)
		{
			insert(begin(), data);
		}
		void pop_front()
		{
			erase(begin());
		}
		void swap(list<T> L)
		{
			swap(_pHead, L._pHead);
		}
	private:
		void CreateHead()
		{
			_pHead = new Node();
			_pHead->_pNext = _pHead;
			_pHead->_pPre = _pHead;
			_pHead->_data = NULL;
		}
	protected:
		Node* _pHead;
	};
}

你可能感兴趣的:(C++)