List和list迭代器的模拟实现

list的使用

我们list表示带头双向循环链表。
我们再找我们的list中每个数据的位置,就不可以再用我们的下标+[]了。
我们就必须用迭代器。

void test_list1()
{
	list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);

	list<int>::iterator it = lt.begin();
	while (it != lt.end())
	{
		cout << *it << " ";
		it++;
	}cout << endl;
	list<int>::iterator found = find(lt.begin(), lt.end(), 3);
	lt.insert(found, 20);
	for (auto n : lt)
	{
		cout << n << " ";
	}
	cout << endl;
}
int main()
{
	test_list1();
	return 0;
}

sort的使用

我们库里面有sort,可以给我们的容器使用,那为什么我们链表不用我们库里的sort,而自己有自己的sort
是因为他用不了库里面的sort

理论而言,模板的语法上可以传任意类型的参数,但是内部使用迭代器是由要求的,名字会暗示你要传随机迭代器

在这里插入图片描述
List和list迭代器的模拟实现_第1张图片
第一个是库里的迭代器,是随机迭代器,下面是list中的迭代器类型,是双向迭代器,所以我们才不能用。

迭代器的分类
  1. 单向迭代器 (++)
  1. 双向迭代器(++ – )
  1. 随机迭代器(++ – + -)

其他的用法基本跟string和vector相似,我们大家举一反三就可以。

list的模拟实现

①list中链表的结点

就是我们链表的结点的内容,我们用一个类来表示

需要注意的就是我们用struct表示,因为他默认是公开的,我们之后都很一直要用它,设置成私有我们访问不了很麻烦

template<class T>
struct list_node
{
	T _val;
	list_node<T>* _next;
	list_node<T>* _prev;
};

②list的类中的成员变量和构造函数

我们list成员变量,已经我们怎么初始化

template<class T>
class list
{
public:
	//构造函数,进行初始化
	list()
	{
		//先创建一个哨兵位的头结点,
		//构成最简单的带头双向循环链表
		_head = new list_node;
		_head->_next = _head;
		_head->_prev = _head;
	}
private:
	//成员变量
	//链表的头结点。
	list_node* _head;
};

我上面的内容其实是有点错误的。
我们要想知道错误的点是什么,我们就明白类名,和类型的区别。

类名和类型
在我们没有模板参数的时候,我们类名就是表示类型。
但是有了类模板之后,我们就不可以这样认为了。
类名就是类名,表示类的名字。
如果我们想表示类型,我们就要加上模板参数,这样才叫类型。
所以我们再定义这个类的对象的时候,一定要写完整。
template<class T>
class list
{
public:
	list()
	{
		_head = new list_node<T>;
		_head->_next = _head;
		_head->_prev = _head;
	}
private:
	list_node<T>* _head;
};

但是我们为了美观、易读和我们以后操作方便,我们将这个类型重命名一下。

	template<class T>
	class list
	{
		typedef list_node<T> node;
	public:
		list()
		{
			_head = new node;
			_head->_next = _head;
			_head->_prev = _head;
		}
	private:
		node* _head;
	};

③尾插

跟我们的链表尾插的功能基本上是一样的。

void push_back(const T& x)
{
	//创建一个新结点,我们再new的时候走的构造函数。
	// 我们可以这样理解,node(x)是一个匿名对象。
	//所以我们将其 类list_node 写一个构造函数。
	node* newnode = new node(x);
	//找到尾
	node* tail = _head->_prev;
	//插入
	tail->_next = newnode;
	newnode->_prev = tail;
	newnode->_next = _head;
	_head->_prev = newnode;
}

我们将list_node的构造函数补上。

template<class T>
struct list_node
{
	T _val;
	list_node<T>* _next;
	list_node<T>* _prev;
	//默认构造 
	list_node(const T& x =T())
		:_next(nullptr)
		,_prev(nullptr)
		,_val(x)
	{}
};

insert 头插,尾插

对于list插入来说,并不会导致迭代器的失效

//pos位置之前
void insert(iterator pos, const T& x)
{
	node* newnode = new node(x);

	node* cur = pos._node;
	node* prev = cur->_prev;

	prev->_next = newnode;
	newnode->_prev = prev;
	newnode->_next = cur;
	cur->_prev = newnode;
}

当有了insert,list的头插和为尾插我们就可以很好的解决

//尾插
void push_back(const T& x)
{
	insert(end(), x);
}
//头插
void push_front(const T& x)
{
	insert(begin(), x);
}

erase 头删 尾删

他会导致迭代器失效,因为迭代器指向的位置没了

iterator erase(iterator pos)
{
	assert(pos != end());
	node* next = pos._node->_next;
	node* prev = pos._node->_prev;

	prev->_next = next;
	next->_prev = prev;
	delete pos._node;
	return iterator(next);
}

当有了erase,list的头删和为尾删我们就可以很好的解决

//头删
void pop_front(const T& x)
{
	erase(begin());
}
//尾删
void pop_back(const T& x)
{
	erase(--end());
}

⑥析构函数

我们在进行析构,我们先写一个函数将我们的结点清除。但是不清除头结点。

在删除的时候会迭代器失效,所以我们在erase加一个返回值解决迭代器失效的问题。返回下一个结点的位置

void clear()
{
	iterator it = begin();
	while (it != end())
	{
		//防止迭代器失效,增加返回值
		it = erase(it);
	}
}

析构就是将我们的头结点也删除掉

~list()
{
	clear();
	delete _head;
	_head = nullptr;
}

⑦迭代器区间的构造函数

就是用迭代器来构造我们的list

		//迭代器区间的构造函数
		template<class Iterator>
		list(Iterator first, Iterator last)
		{
			//我们没有头结点,就不能push_back
			_head = new node;
			_head->_next = _head;
			_head->_prev = _head;
			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}

⑧迭代器区间的拷贝构造

list(const list<T>& lt)
{
	_head = new node;
	_head->_next = _head;
	_head->_prev = _head;
	for (auto e : lt)
	{
		push_back(e);
	}
}

另一种拷贝构造的写法,比较现代的写法

void swap(list<T>& tmp)
{
	std::swap(_head, tmp._head);
}
list(const list<T>& lt)
{
	empty_init();
	list<T> tmp(lt.begin(), lt.end());
	swap(tmp);
}

⑨赋值重载

比较现代的写法

void swap(list<T>& tmp)
{
	std::swap(_head, tmp._head);
}
list<T>& operator = (list<T> lt)
{
	swap(lt);
	return *this;
}

④迭代器(最重要的)

对于我们字符串和数组的迭代器,我们可以认为一个指针,因为他们的空间连续,所以我们对指针加加,我们就可以将他们遍历一遍。

但是对于链表,它的每一个结点都是一个类。
我们想将它遍历一遍,它的空间也不连续,我们对指针加加也不能指向下一个空间。

大佬将迭代器设为一个类。我们通过将其封装能够让我们找到下一个结点的位置。下面我们就看看怎么封装的。

总结一下迭代器

1.迭代器要么是原生指针
2.迭代器要么就是自定义类型对原生指针的封装,模拟指针的行为。

list迭代器的封装

首先我们要知道我们迭代器要有什么,并且要实现什么功能。

功能:我们能够遍历链表,并且能够将链表的值返回出来。
实现:就可以用操作符重载,将++*重载一下。
++找到链表的下一个位置,
*返回链表的值。
!=,再遍历最后我们要停下来就要进行比较。

Ⅰ、迭代器的类的内容

template<class T>
//因为迭代器也是公开的所以我们用struct
struct __list_iterator
{
	//重命名我们如果想要修改的化就修改重命名的内容
	//而且看着很容易
	typedef __list_iterator<T> iterator;

	typedef list_node<T> node;
	//用结点的指针构造一个迭代器
	node* _node;

	//迭代器的构造函数
	__list_iterator(node* n)
		:_node(n)
	{}
	T& operator*()
	{
		return _node->_val;
	}
	iterator& operator++()
	{
		_node= _node->_next;
		return *this;  
	}
	//后置加加
	iterator operator++(int)
	{
		iterator tmp(_node);
		_node = _node->_next;
		return tmp;
	}
	//前置--
	iterator& operator--()
	{
		_node = _node->_prev;
		return *this;
	}
	//后置减减
	iterator operator--(int)
	{
		iterator tmp(_node);
		_node = _node->_prev;
		return tmp;
	}
	bool operator!=(const iterator& s)
	{
		return _node != s._node;
	}
	bool operator==(const iterator& s)
	{
		return _node == s._node;
	}
};

Ⅱ、在类中使用迭代器

这时,我们将迭代器的类写完了,我们就可以用迭代器。

template<class T>
class list
{
	typedef list_node<T> node;
	//将类的迭代器重命名一下,方便我们的使用
	typedef  __list_iterator<T> iterator;
	iterator begin()
	{
		//构建一个迭代器返回
		//第一种方法
		//iteartor it(_head->next);
		//return it;
		//第二种方法用匿名对象
		return iterator(_head->_next); 
	}
	iterator end()
	{
		return iterator(_head);
	}
public:
	list()
	{
		_head = new node;
		_head->_next = _head;
		_head->_prev = _head;
	}
private:
	node* _head;
};

我们封装的作用就体现出来了,让我们的操作跟前面vector一样。

Ⅲ、const迭代器

要有const迭代器,就再写一个const迭代器的类。如下面代码

template<class T>
//因为迭代器也是公开的所以我们用struct
struct __list_const_iterator
{
	//重命名我们如果想要修改的化就修改重命名的内容
	//而且看着很容易
	typedef __list_const_iterator<T> iterator;

	typedef list_node<T> node;
	//用结点的指针构造一个迭代器
	node* _node;

	//迭代器的构造函数
	__list_const_iterator(node* n)
		:_node(n)
	{}
	const T& operator*()
	{
		return _node->_val;
	}
	//前置加加
	iterator& operator++()
	{
		_node = _node->_next;
		return *this;
	}
	//后置加加
	iterator operator++(int)
	{
		iterator tmp(_node);
		_node = _node->_next;
		return tmp;
	}
	//前置--
	iterator& operator--()
	{
		_node = _node->_prev;
		return *this;
	}
	//后置减减
	iterator operator--(int)
	{
		iterator tmp(_node);
		_node = _node->_prev;
		return tmp;
	}
	bool operator!=(const iterator& s)
	{
		return _node != s._node;
	}
	bool operator==(const iterator& s)
	{
		return _node == s._node;
	}
};

在类中用const迭代器

	template<class T>
	class list
	{
		typedef list_node<T> node;
	public: 
		typedef  __list_const_iterator<T> const_iterator;
		const_iterator begin() const
		{
			return const_iterator(_head->_next);
		}
		const_iterator end()const
		{
			return const_iterator(_head);
		}

		list()
		{
			_head = new node;
			_head->_next = _head;
			_head->_prev = _head;
		}
	private:
		node* _head;
	};

我们要注意const修饰的对象是谁,有的修饰this指针,有的修饰迭代器,不一样,这些小细节,错一个都不行。

我们提一个问题,能不能在typedef中进行这样的操作,然后就不用写const迭代器呢。

	typedef  __list_iterator<T> iterator;
	typedef  const iterator const_iterator;
	//就是将我们的正向迭代器前加一个const表示我们的const迭代器,
	//既然我们后面没有用这种方法,肯定不行,至于为什们大家必须想明白
为什们不能用上述方法
首先我们必须要明白const修饰的对象是谁,修饰的对象,不一样我们的效果也不一样。
const int * p = &i,const修饰的是 *p,p指向的内容(*p)不可修改,但是p却可以修改。
我们的const迭代器想要的就是这种效果,迭代器可以++,但是迭代器解引用后指向的内容不可修改。
而我们的const迭代器就是将在解引用的时候传引用返回,变成const引用。
int * const p = &i,const修饰的对象是 p,p不可以修改,但是p指向的内容(*p)可以修改。
我们用这样的迭代器肯定是不对的,
typedef const __list_iterator const_iterator;
这是我们typedef的想法,我们理解它不能就要理解const所要修饰对象。我们说迭代器就相当于指针。我们用const修饰这个迭代器的类,我们再用这个类的时候它的this指针被const修饰,而我们++的操作 _node = _node->_next;也就不可以++了。所以它可以类比成==> T *const。

但是我们发现,我们的正向迭代器和const正向迭代器,好像基本一样,就是引用返回的地方不一样,那为什么不合在一块呢?

Ⅳ、将两个迭代器合在一起

既然我们就几个地方不一样,那么我们再用模板的是再多一个参数,让编译器自己做类的实例化,我们相似的代码写一份就好了呀。

//增加一个模板参数
template<class T,class Ref>
struct __list_iterator
{

	typedef __list_iterator<T,Ref> iterator;

	typedef list_node<T> node;
	node* _node;

	__list_iterator(node* n)
		:_node(n)
	{}
	Ref operator*()
	{
		return _node->_val;
	}
	iterator& operator++()
	{
		_node = _node->_next;
		return *this;
	}
	iterator operator++(int)
	{
		iterator tmp(_node);
		_node = _node->_next;
		return tmp;
	}
	iterator& operator--()
	{
		_node = _node->_prev;
		return *this;
	}
	iterator  operator--(int)
	{
		iterator tmp(_node);
		_node = _node->_prev;
		return tmp;
	}
	bool operator!=(const iterator& s)
	{
		return _node != s._node;
	}
	bool operator==(const iterator& s)
	{
		return _node == s._node;
	}
};

那我们在list类中怎么用它呢。

template<class T >
class list
{
	typedef list_node<T> node;
public: 

	typedef  __list_iterator<T, T&> iterator;
	typedef  __list_iterator<T,const T&> const_iterator;

	iterator begin()
	{
		return iterator(_head->_next); 
	}
	iterator end()
	{
		return iterator(_head);
	}
	const_iterator begin() const
	{
		return const_iterator(_head->_next);
	}
	const_iterator end()const
	{
		return const_iterator(_head);
	}

	list()
	{
		_head = new node;
		_head->_next = _head;
		_head->_prev = _head;
	}
private:
	node* _head;
};

只要我们再用迭代器的时候我们传两个参数,就可以很容易的简化代码,但是效率并不会提升,只是编译器帮我们做了这些工作。

Ⅴ、迭代器的第三个参数

如果有一个自定义类型,我们想去用这个自定义类型当我们的链表,并且我们还想要访问我们的自定义类型里的数据,我们怎么办。

struct AA
{
	//默认构造
	AA(int a1 = 0, int a2 = 0)
		: _a1(a1)
		,_a2(a2)
	{}

	int _a1;
	int _a2;
};
void test_list2()
{
	list<AA> lt;
	lt.push_back(AA(1, 2));
	lt.push_back(AA());
	lt.push_back(AA(2, 1));
	list<AA>::iterator it = lt.begin();
	while (it != lt.end())
	{
		cout << (*it)._a1 << ":" << (*it)._a2 << endl;
		it++;
	}
	cout << endl;
}

想访问AA中的元素,我们上面给了一种做法就是解引用然后再找,因为我们的迭代器中重载了解引用操作符,所以我们可以用。

我们知道迭代器是一个指针,指针直接用->不就可以了吗?
所以只需要重载->就可以了。

迭代器中重载->

T* operator->()
{
	return &_node->_val;
}
list<AA>::iterator it = lt.begin();
while (it != lt.end())
{
	cout << it->_a1 << ":" << it->_a2 << endl;
	it++;
}

这样用了我们就可以使用->去访问自定义类型中的元素了。

为什们这样重载 ->?
将结点的自定义类型的地址返回,我们知道自定义类型的指针,对于结构体而言就可以使用 ->
但是我感觉大家会有疑问?
当重载完 ->it->表示AA类型的地址,不应该再用一个 ->才能够指向 _a1吗?
其实是为了可读性,省略了一个箭头。所以我们就可以调用了。
编译器会进行特殊处理

第三个参数

对于const迭代器的重载->,我们返回应该返回const T*.

const T* operator->()
{
	return &_node->_val;
}

所以我们可以在模板中再加一个参数,用来指这个。

Ⅵ迭代器最终形态

我们有三个模板参数就是为了搞const迭代器

//增加一个模板参数
template<class T,class Ref,class Ptr>
struct __list_iterator
{

	typedef __list_iterator<T,Ref,Ptr> iterator;

	typedef list_node<T> node;
	node* _node;

	__list_iterator(node* n)
		:_node(n)
	{}
	Ref operator*()
	{
		return _node->_val;
	}
	Ptr operator->()
	{
		return &_node->_val;
	}
	iterator& operator++()
	{
		_node = _node->_next;
		return *this;
	}
	iterator operator++(int)
	{
		iterator tmp(_node);
		_node = _node->_next;
		return tmp;
	}
	iterator& operator--()
	{
		_node = _node->_prev;
		return *this;
	}
	iterator  operator--(int)
	{
		iterator tmp(_node);
		_node = _node->_prev;
		return tmp;
	}
	bool operator!=(const iterator& s)
	{
		return _node != s._node;
	}
	bool operator==(const iterator& s)
	{
		return _node == s._node;
	}
};

在类中如何用

template<class T >
class list
{
	typedef list_node<T> node;
public: 
	//将类的迭代器重命名一下,方便我们的使用
	typedef  __list_iterator<T, T&, T*> iterator;
	typedef  __list_iterator<T, const T&, const T*> const_iterator;
	//typedef  __list_const_iterator const_iterator;
	iterator begin()
	{
		//构建一个迭代器返回
		//第一种方法
		//iteartor it(_head->next);
		//return it;
		//第二种方法用匿名对象
		return iterator(_head->_next); 
	}
	iterator end()
	{
		return iterator(_head);
	}
	const_iterator begin() const
	{
		return const_iterator(_head->_next);
	}
	const_iterator end()const
	{
		return const_iterator(_head);
	}

	list()
	{
		_head = new node;
		_head->_next = _head;
		_head->_prev = _head;
	}
private:
	node* _head;
};

list模拟实现的代码

list.h

#pragma once
#include
namespace tongtong
{
	template<class T>
	struct list_node
	{
		T _val;
		list_node<T>* _next;
		list_node<T>* _prev;

		list_node(const T& x =T())
			:_next(nullptr)
			,_prev(nullptr)
			,_val(x)
		{}
	};
	//template
	因为迭代器也是公开的所以我们用struct
	//struct __list_iterator
	//{
	//	//重命名我们如果想要修改的化就修改重命名的内容
	//	//而且看着很容易
	//	typedef __list_iterator iterator;

	//	typedef list_node node;
	//	//用结点的指针构造一个迭代器
	//	node* _node;

	//	//迭代器的构造函数
	//	__list_iterator(node* n)
	//		:_node(n)
	//	{}
	//	T& operator*()
	//	{
	//		return _node->_val;
	//	}
	//	//前置加加
	//	iterator& operator++()
	//	{
	//		_node = _node->_next;
	//		return *this;
	//	}
	//	//后置加加
	//	iterator operator++(int)
	//	{
	//		iterator tmp(_node);
	//		_node = _node->_next;
	//		return tmp;
	//	}
	//	//前置--
	//	iterator& operator--()
	//	{
	//		_node = _node->_prev;
	//		return *this;
	//	}
	//	//后置减减
	//	iterator operator--(int)
	//	{
	//		iterator tmp(_node);
	//		_node = _node->_prev;
	//		return tmp;
	//	}
	//	bool operator!=(const iterator& s)
	//	{
	//		return _node != s._node;
	//	}
	//	bool operator==(const iterator& s)
	//	{
	//		return _node == s._node;
	//	}
	//};
	//template
	//因为迭代器也是公开的所以我们用struct
	//struct __list_const_iterator
	//{
	//	//重命名我们如果想要修改的化就修改重命名的内容
	//	//而且看着很容易
	//	typedef __list_const_iterator iterator;

	//	typedef list_node node;
	//	//用结点的指针构造一个迭代器
	//	node* _node;

	//	//迭代器的构造函数
	//	__list_const_iterator(node* n)
	//		:_node(n)
	//	{}
	//	const T& operator*()
	//	{
	//		return _node->_val;
	//	}
	//	//前置加加
	//	iterator& operator++()
	//	{
	//		_node = _node->_next;
	//		return *this;
	//	}
	//	//后置加加
	//	iterator operator++(int)
	//	{
	//		iterator tmp(_node);
	//		_node = _node->_next;
	//		return tmp;
	//	}
	//	//前置--
	//	iterator& operator--()
	//	{
	//		_node = _node->_prev;
	//		return *this;
	//	}
	//	//后置减减
	//	iterator operator--(int)
	//	{
	//		iterator tmp(_node);
	//		_node = _node->_prev;
	//		return tmp;
	//	}
	//	bool operator!=(const iterator& s)
	//	{
	//		return _node != s._node;
	//	}
	//	bool operator==(const iterator& s)
	//	{
	//		return _node == s._node;
	//	}
	//};
	

	//增加一个模板参数
	template<class T,class Ref,class Ptr>
	struct __list_iterator
	{
	
		typedef __list_iterator<T,Ref,Ptr> iterator;

		typedef list_node<T> node;
		node* _node;

		__list_iterator(node* n)
			:_node(n)
		{}
		Ref operator*()
		{
			return _node->_val;
		}
		Ptr operator->()
		{
			return &_node->_val;
		}
		iterator& operator++()
		{
			_node = _node->_next;
			return *this;
		}
		iterator operator++(int)
		{
			iterator tmp(_node);
			_node = _node->_next;
			return tmp;
		}
		iterator& operator--()
		{
			_node = _node->_prev;
			return *this;
		}
		iterator  operator--(int)
		{
			iterator tmp(_node);
			_node = _node->_prev;
			return tmp;
		}
		bool operator!=(const iterator& s)
		{
			return _node != s._node;
		}
		bool operator==(const iterator& s)
		{
			return _node == s._node;
		}
	};
	template<class T >
	class list
	{
		typedef list_node<T> node;
	public: 
		//将类的迭代器重命名一下,方便我们的使用
		typedef  __list_iterator<T, T&, T*> iterator;
		typedef  __list_iterator<T, const T&, const T*> const_iterator;
		//typedef  __list_const_iterator const_iterator;
		iterator begin()
		{
			//构建一个迭代器返回
			//第一种方法
			//iteartor it(_head->next);
			//return it;
			//第二种方法用匿名对象
			return iterator(_head->_next); 
		}
		iterator end()
		{
			return iterator(_head);
		}
		const_iterator begin() const
		{
			return const_iterator(_head->_next);
		}
		const_iterator end()const
		{
			return const_iterator(_head);
		}
		void empty_init()
		{
			_head = new node;
			_head->_next = _head;
			_head->_prev = _head;
		}
		list()
		{
			empty_init();
		}

		//迭代器区间的构造函数
		template<class Iterator>
		list(Iterator first, Iterator last)
		{
			//我们没有头结点,就不能push_back
			empty_init();
			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}

		//list(const list& lt)
		//{
		//	empty_init();
		//	for (auto e : lt)
		//	{
		//		push_back(e);
		//	}
		//}
		void swap(list<T>& tmp)
		{
			std::swap(_head, tmp._head);
		}
		list(const list<T>& lt)
		{
			empty_init();
			list<T> tmp(lt.begin(), lt.end());
			swap(tmp);
		}
		list<T>& operator = (list<T> lt)
		{
			swap(lt);
			return *this;
		}
		//尾插
		void push_back(const T& x)
		{
			//创建一个新结点,我们再new的时候走的构造函数。
			// 我们可以这样理解,node(x)是一个匿名对象。
			//所以我们将其 类list_node 写一个构造函数。
			//node* newnode = new node(x);
			找到尾
			//node* tail = _head->_prev;
			插入
			//tail->_next = newnode;
			//newnode->_prev = tail;
			//newnode->_next = _head;
			//_head->_prev = newnode;
			insert(end(), x);
		}
		//头插
		void push_front(const T& x)
		{
			insert(begin(), x);
		}


		//pos位置之前
		void insert(iterator pos, const T& x)
		{
			node* newnode = new node(x);

			node* cur = pos._node;
			node* prev = cur->_prev;

			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
		}
		iterator erase(iterator pos)
		{
			assert(pos != end());
			node* next = pos._node->_next;
			node* prev = pos._node->_prev;

			prev->_next = next;
			next->_prev = prev;
			delete pos._node;
			return iterator(next);
		}
		//头删
		void pop_front(const T& x)
		{
			erase(begin());
		}
		//尾删
		void pop_back(const T& x)
		{
			erase(--end());
		}

		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}
		//清理结点,但是不清理头结点
		void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				//防止迭代器失效,增加返回值
				it = erase(it);
			}
		}
	private:
		node* _head;
	};


	void print_list(const list<int>& lt)
	{
		list<int>::const_iterator cit = lt.begin();
		while (cit != lt.end())
		{
			/*(*cit)  *= 2;*/
			cout << *cit << " ";
			cit++;
		}
		cout << endl;
	}
	void test_list1()
	{
		list<int> lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_back(3);
		lt.push_back(4);
		//list::iterator it = lt.begin();
		//while (it != lt.end())
		//{
		//	cout << *it << " ";
		//	++it;
		//}
		//cout << endl;
		//auto rit = lt.begin();
		//rit++;
		//lt.insert(rit, 20);
		//for (auto c : lt)
		//{
		//	cout << c << " ";
		//}
		//cout << endl;
		//print_list(lt);

		//lt.clear();
		for (auto c : lt)
		{
			cout << c << " ";
		}
		cout << endl;
		list<int> lt2 ;
		lt2 = lt;
		for (auto c : lt2)
		{
			cout << c << " ";
		}
		cout << endl;
		for (auto c : lt)
		{
			cout << c << " ";
		}
		cout << endl;
	}

	struct AA
	{
		//默认构造
		AA(int a1 = 0, int a2 = 0)
			: _a1(a1)
			,_a2(a2)
		{}

		int _a1;
		int _a2;
	};
	void test_list2()
	{
		list<AA> lt;
		lt.push_back(AA(1, 2));
		lt.push_back(AA());
		lt.push_back(AA(2, 1));
		list<AA>::iterator it = lt.begin();
		while (it != lt.end())
		{
			cout << it->_a1 << ":" << it->_a2 << endl;
			it++;
		}
		cout << endl;
	}
}
 	

test.cpp

#define _CRT_SECURE_NO_WARNINGS 1 
#include
#include

using namespace std;
#include"list.h"
int main()
{
	tongtong::test_list1();
	return 0;
}

你可能感兴趣的:(C++,链表,数据结构,list)