C++ list模拟实现

        在前面我已经过讲过list的使用,但是如果想进一步提高自己的话,还是要深入了解底层实现的。在这里博主带大家一起走进list的底层实现。当然,我模拟实现的list肯定没有官方实现的优秀,还是那句话,我们不是造更好的轮子,而是帮助我们更深入了解底层~ 

目录

成员变量的定义

struct ListNode

struct __list_iterator

class list

class reverse_iterator

成员函数

struct ListNode

struct __list_iterator

扫描二维码关注公众号,回复: 14281041 查看本文章

__list_iterator(Node*x)

Ref operator*()

Ptr operator->()

self& operator++()

self operator++(int)

self& operator--()

self operator--(int)

bool operator != (const self& it) const

bool operator == (const self& it) const

class list

iterator begin()

iterator end()

const_iterator begin() const

const_iterator end() const

reverse_iterator rbegin()

reverse_iterator rend()

 list()

list(size_t n, const T& val = T())

list(int n, const T& val = T())

list(InputIterator first, InputIterator last)

list(const list& lt) 

方法二:传统写法

list& operator=(list lt)

方法二:传统写法:

~list()

void clear()

void push_front(const T& x)

void pop_front()

void push_back(const T& x)

void pop_back()

iterator insert(iterator pos, const T& x)

iterator erase(iterator pos)

class reverse_iterator

reverse_iterator(Iterator it)

Ref operator*()

方法二:

  Ptr operator->()

方法二:

self& operator++()

self operator++(int)

self& operator--()

self operator--(int)

bool operator!=(const self& rit) const

bool operator==(const self& rit) const

完整代码

list.h

reverse_iterator.h

测试代码


成员变量的定义

struct ListNode

template<class T>
struct ListNode:
	ListNode<T>* _prev;
	ListNode<T>* _next;
	T _data;

struct __list_iterator

//封装一个迭代器
template<class T, class Ref, class Ptr>
struct __list_iterator
	typedef ListNode<T> Node;
typedef __list_iterator<T, Ref, Ptr> self; //一个迭代器对象

typedef Ref reference;
typedef Ptr pointer;
Node* _node;

class list

template<class T>
class list
	typedef ListNode<T> Node;
public:
	typedef __list_iterator<T, T&, T*> iterator;
	typedef __list_iterator<T, const T&, const T*> const_iterator; //第一个T是表示类型,不加const

	typedef reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;
	typedef reverse_iterator<iterator, T&, T*> reverse_iterator;
private:
	Node* _head;

class reverse_iterator

//适配器
//Iterator是哪个容器的迭代器,reverse_iterator<Iterator>就可以
//适配出哪个容器的反向迭代器,复用的体现
template<class Iterator, class Ref, class Ptr>
class reverse_iterator
	typedef reverse_iterator<Iterator, Ref, Ptr> self;
private:
	Iterator _it;

成员函数

struct ListNode

	ListNode(T data = T())
		:_prev(nullptr)
		,_next(nullptr)
		,_data(data)
	{}

    ListNode(T data = T())
        :_prev(nullptr)
        ,_next(nullptr)
        ,_data(data)
    {}

       struct ListNode是我们定义一个结点的类,上面展示它的成员变量,在这里构造函数是完成对该类的初始化。这样我们每次new出来的结点,都是初始化过的。(new出来的会自动调用类里面的构造函数.)

 

struct __list_iterator

__list_iterator(Node*x)

	__list_iterator(Node*x)
		:_node(x)
	{}

//对迭代器进行封装,这里对其构造函数初始化,   

 __list_iterator(Node*x)
        :_node(x) //将传过来的结点x传给_node。在这里, _node会自动调用它的(struct ListNode类在这里由于没有显示实现拷贝构造,所以会调用编译器默认生成的)拷贝构造函数来完成初始化。
    {}

Ref operator*()

	Ref operator*()
	{
		return _node->_data;
	}

    Ref operator*()  //Ref在这里是返回的引用,如果list类里面传过来的T&就返回的是T&;如果是const T&就返回的是const T&。

思考:

为什么要有Ref呢?如果我们只在上面定义template<class T>。

        会不会存在这种场景,迭代器里面有写成员可能让我们返回T&,或者指针。如果不使用多个模板参数参数的话,在实现时就会大量的拷贝,有很多重复的地方(在内部基本上对某些要求的成员函数返回值进行修改:T& ,const T&...)。所以我们在这里实现多个模板参数,这样返回值就可以有更多的自主选择来满足我们的需求。
    {
        return _node->_data;
    }

Ptr operator->()

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

    Ptr operator->() //Ptr和上面Ref类似,只不过Ptr代表是返回指针。
    {
        return &_node->_data;/返回结点里面数据(T)的地址
    }

我们应该这样使用:

p.operator->() / p->operator->();//不知道内部成员变量名的话就这么用,不用显示调p->_data(库里面不一定是_data)

self& operator++()

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

    //++it
    self& operator++() //正向迭代器,前置++ 往后迭代。
    {
        _node = _node->_next; //往后迭代
        return *this; //返回++后的对象self。self:typedef __list_iterator<T, Ref, Ptr> self; 
    }

self operator++(int)

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

    //it++ 后置++
    self operator++(int)  //int是表示占位,是为了与前置++进行函数重载。
    {
        self tmp(*this); //先拷贝构造一个临时对象,方便返回。以免++后,就找不到++前的结点了。——> 在这里有一个拷贝构造,所以我们尽量使用前置++,代码效率会更高。
        _node = _node->_next;
        return tmp; //返回tmp对象,因为这是后置++,++后的结果在这里不返回。tmp是临时对象,所以上面不能传引用返回!
    }

self& operator--()

	//--it
	self& operator--()
	{
		_node = _node->_prev;
		return *this;
	}

    //--it  前置--
    self& operator--()
    {
        _node = _node->_prev; //往前迭代。
        return *this; //返回迭代后的对象。
    }

self operator--(int)

	//it--
	self operator--(int)
	{
		self tmp(*this); //先构造一个临时对象
		_node = _node->_prev;
		return tmp;
	}

    //it--
    self operator--(int)
    {
        self tmp(*this); //先构造一个临时对象。同理,后置--涉及一次拷贝构造,所以前置--效率比后置--效率高。
        _node = _node->_prev;
        return tmp; //tmp是临时对象,在这里不能传引用返回。
    }

bool operator != (const self& it) const

	bool operator != (const self& it) const
	{
		return _node != it._node;
	}

bool operator == (const self& it) const

	bool operator == (const self& it) const
	{
		return _node == it._node;
	}

        上面的成员函数,和string、vector基本类似,在之前的博客已经详细介绍过了,在这里我就不再赘述了~

class list

iterator begin()

	iterator begin()
	{
		return iterator(_head->_next); //Node*
	}

    iterator begin()
    {
        return iterator(_head->_next); //调用正向迭代器里面的构造函数,在这里返回的是匿名对象。我们发现匿名对象有时候用起来也是很爽的。
    }

iterator end()

	iterator end()
	{
		return iterator(_head); //Node*
	}

const_iterator begin() const

	const_iterator begin() const //不加const会冲突,下面也一样
	{
		return const_iterator(_head->_next);
	}

const_iterator end() const

	const_iterator end() const
	{
		return const_iterator(_head);
	}

reverse_iterator rbegin()

	reverse_iterator rbegin()
	{
		return reverse_iterator(end());
	}

    reverse_iterator rbegin()
    {
        return reverse_iterator(end()); //调用了反向迭代器的构造函数,在这里rbegin返回的是构造的匿名对象。我们发现匿名对象有时候用起来也是很爽的。

在这里rbegin()指向的是哨兵位头结点。
    }

reverse_iterator rend()

	reverse_iterator rend()
	{
		return reverse_iterator(begin());
	}

还是一样,上面很多都是在之前讲过,在这里我们用之前画的图来表示一下begin()、rbegin()、end()、rend()之间的关系:

 list()

	list() //初始化,构造一个头结点
	{
		_head = new Node();
		_head->_next = _head;
		_head->_prev = _head;
	}

    list() //初始化,构造一个头结点
    {
        _head = new Node(); //初始化头结点里指针的关系。
        _head->_next = _head;
        _head->_prev = _head;

                                         
    } 

list(size_t n, const T& val = T())

	list(size_t n, const T& val = T())
	{
		_head = new Node; //加不加括号都可以
		_head->_next = _head;
		_head->_prev = _head;
		for (size_t i = 0; i < n; i++)
		{
			push_back(val);
		}
	}

    list(size_t n, const T& val = T())
    {
        _head = new Node; //加不加括号都可以
        _head->_next = _head;
        _head->_prev = _head;  

        //这个也是构造函数,我们第一步要主动初始化哨兵位头结点。
        for (size_t i = 0; i < n; i++)  //循环n次,把n个val数据一次插入
        {
            push_back(val); //调用push_back()接口进行尾插。
        }
    }

list(int n, const T& val = T())

	list(int n, const T& val = T())
	{
		_head = new Node; //加不加括号都可以
		_head->_next = _head;
		_head->_prev = _head;
		for (int i = 0; i < n; i++)
		{
			push_back(val);
		}
	}

list(int n, const T& val = T()):这个函数和上面的函数构成函数重载,在这里实现这个版本是为了解决一个bug。

list(InputIterator first, InputIterator last)

	template<class InputIterator>
	list(InputIterator first, InputIterator last)
	{
		_head = new Node();
		_head->_next = _head;
		_head->_prev = _head;
		while (first != last)
		{
			push_back(*first);
			first++;
		}
	}

    template<class InputIterator> //普通迭代器
    list(InputIterator first, InputIterator last) //迭代器区间进行初始化。
    {
        _head = new Node();
        _head->_next = _head;
        _head->_prev = _head;

        //这个也是构造函数,我们第一步要主动初始化哨兵位头结点。
        while (first != last) //last表示最后一个数据的下一个位置的迭代器。
        {
            push_back(*first); //*first,拿到迭代器里面结点中的数据。*是重载过的。
            first++;
        }
    }

list(const list<T>& lt) 

	list(const list<T>& lt) 
	{
		//先初始化
		_head = new Node();
		_head->_next = _head;
		_head->_prev = _head;

		list<T> tmp(lt.begin(), lt.end()); //复用构造函数
		std::swap(_head, tmp._head);
	}

    list(const list<T>& lt) 
    {
        //先初始化
        _head = new Node();
        _head->_next = _head;
        _head->_prev = _head;

        //拷贝构造也是构造函数,调用拷贝构造构造函数就不会主动调用了

        list<T> tmp(lt.begin(), lt.end()); //复用构造函数
        std::swap(_head, tmp._head); //进行资源的交换,实际上就是交换头结点。
    }//构造的临时对象tmp,会自动调用析构函数,完成资源的清理。

方法二:传统写法

	//lt2(lt1)
	list(const list<T>& lt)
	{
		//先初始化
		_head = new Node();
		_head->_next = _head;
		_head->_prev = _head;
		
		for (auto e : it)
		{
			push_back(e);
		}
	}

list<T>& operator=(list<T> lt)

	list<T>& operator=(list<T> lt) //复用拷贝构造
	{
		std::swap(_head, lt._head);
		return *this;
	}

    list<T>& operator=(list<T> lt) //复用拷贝构造
    {
        std::swap(_head, lt._head); //交换头结点,这时候*this就被赋值好了
        return *this; //返回被赋值好的对象
    } //lt是临时对象,这时候lt自动调用析构函数完成对原*this里的资源清理。

方法二:传统写法:

//lt2=lt1
	list<T>& operator=(list<T>& lt) //复用拷贝构造
	{
		if (this != &lt) //不能上来就清空!!
		{
			clear();
			for (auto e : lt)
			{
				push_back(e);
			}
		}
		return *this;
	}

//lt2=lt1
    list<T>& operator=(list<T>& lt) //传引用
    {
        if (this != &lt) //不能上来就清空!!这里不能给自己赋值
        {
            clear(); //清空自己里面的结点,只剩下一个头结点。
            for (auto e : lt) //依次插入
            {
                push_back(e);
            }
        }
        return *this; 
    } 

~list()

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

    ~list()
    {
        clear(); //调用clear()清空里面的结点,只剩下一个头结点。
        delete _head; //释放头结点
        _head = nullptr; //头结点置空。
    }

void clear()

	void clear()
	{
		iterator it = begin();
		while (it != end())
		{
			iterator del = it++;
			delete del._node; //_node是在list类中new出来的
		}
		//清理完节点后重新链接头结点关系
		_head->_next = _head;
		_head->_prev = _head;

		//iterator it = begin();
		//while (it != end())
		//{
		//	erase(it++); //这里不能分开写
		//}
	}

    void clear()
    {
        iterator it = begin();
        while (it != end())
        {
            iterator del = it++; //提前记录要删除的节点的迭代器
            delete del._node; //_node是在list类中new出来的,不是delete del
        }
        //清理完节点后重新链接头结点关系
        _head->_next = _head;
        _head->_prev = _head;

        //方法二:

        //iterator it = begin();
        //while (it != end())
        //{
        //    erase(it++); //这里不能分开写 这里先返回it++前的临时对象。
        //}
    }

void push_front(const T& x)

	void push_front(const T& x)
	{
		insert(begin(), x);
	}

void pop_front()

	void pop_front()
	{
		erase(begin());
	}

void push_back(const T& x)

	void push_back(const T& x)
	{
		insert(end(), x);//end()不能给成_head,这里是一个迭代器
	}

void pop_back()

	void pop_back()
	{
		erase(--end());
	}

    void pop_back()
    {
        erase(--end()); //end()是哨兵位头结点位置的迭代器,--end()就是哨兵位前一个节点的迭代器,也就是最后一个数据位置的迭代器。
    }

iterator insert(iterator pos, const T& x)

	iterator insert(iterator pos, const T& x)
	{
		Node* prev = pos._node->_prev;
		Node* cur = pos._node;
		Node* newnode = new Node(x);

		prev->_next = newnode;
		newnode->_prev = prev;
		newnode->_next = cur;
		cur->_prev = newnode;
		return iterator(newnode);
	}

    iterator insert(iterator pos, const T& x)
    { 

        //这里一定注意是结点来连接关系,不使用迭代器。
        Node* prev = pos._node->_prev; //prev指向pos迭代器里结点的前一个结点的位置。
        Node* cur = pos._node;//cur指向当前迭代器里的结点
        Node* newnode = new Node(x); //构造新的结点

        prev->_next = newnode;
        newnode->_prev = prev;
        newnode->_next = cur;
        cur->_prev = newnode;
        return iterator(newnode); //iterator(newnode)构造匿名迭代器对象并返回。
    }

iterator erase(iterator pos)

	//erase之后,it就失效了
	iterator erase(iterator pos)
	{
		assert(pos != end()); //头结点不能删
		Node* prev = pos._node->_prev;
		Node* next = pos._node->_next;
		prev->_next = next;
		next->_prev = prev;

		delete pos._node;
		return iterator(next);
	}

    //erase之后,it就失效了
    iterator erase(iterator pos)
    {
        assert(pos != end()); //头结点不能删
        Node* prev = pos._node->_prev; //这里一定注意是结点来连接关系,不使用迭代器。
        Node* next = pos._node->_next;
        prev->_next = next;
        next->_prev = prev;

        delete pos._node;
        return iterator(next); //返回删除结点的下一个结点位置的迭代器。
    }

class reverse_iterator

reverse_iterator(Iterator it)

	reverse_iterator(Iterator it)
		:_it(it)
	{}

//Iterator是哪个容器的迭代器,reverse_iterator<Iterator>就可以适配出哪个容器的反向迭代器,复用的体现    

reverse_iterator(Iterator it) //Iterator可以说是容器适配器。
        :_it(it)
    {}

Ref operator*()

	Ref operator*()
	{
		Iterator prev = _it;
		return *--prev;
	}

    Ref operator*()
    {
        Iterator prev = _it;  //_it是构造好出来的Iterator对象。为了防止_it被修改掉,我们用prev来提前记录一下。
        return *--prev; //这里解引用我们发现并不是直接解引用,而是解引用当前迭代器的前一个迭代器。


    } 

方法二:

	// 1、这时候Iterator还没有实例化,还没法使用::,这时候需要使用typename提前告知有这个类型
	typename Iterator::reference operator*()
	{
		Iterator prev = _it;
		return *--prev;
	}

  Ptr operator->()

	Ptr operator->()
	{
		return &operator*();
	}

    Ptr operator->()
    {
        return &operator*(); //返回*结点数据的地址
    }

方法二:

	// 1、这时候Iterator还没有实例化,还没法使用::,这时候需要使用typename提前告知有这个类型
	typename Iterator::pointer operator->()
	{
		return &operator*();
	}

self& operator++()

	self& operator++()
	{
		--_it;
		return *this;
	}

    self& operator++()
    {
        --_it;  //反向迭代器的++对应正向迭代器的--,实际上这里又调用了正向迭代器里的operator--
        return *this;
    }

self operator++(int)

	self operator++(int)
	{
		self tmp(*this);
		--_it;
		return tmp;
	}

self& operator--()

	self& operator--()
	{
		++_it;
		return *this;
	}

    self& operator--()
    {
        ++_it; //反向迭代器的--对应正向迭代器的++,实际上这里又调用了正向迭代器里的operator++
        return *this;
    }

self operator--(int)

	self operator--(int)
	{
		self tmp(*this);
		++_it;
		return tmp;
	}

bool operator!=(const self& rit) const

	bool operator!=(const self& rit) const
	{
		return _it != rit._it;
	}

bool operator==(const self& rit) const

	bool operator==(const self& rit) const
	{
		return _it == rit._it;
	}

        上面的成员函数接口都是类似,之前都有很详细的介绍,在这里我就不再赘述了,如果有不懂得地方,或者我有错误的地方可以来私信我。

完整代码

list.h

#pragma once
#include<iostream>
#include<assert.h>
#include"reverse_iterator.h"
using namespace std;

namespace cyq
{
template<class T>
struct ListNode
{
	ListNode<T>* _prev;
	ListNode<T>* _next;
	T _data;

	ListNode(T data = T())
		:_prev(nullptr)
		,_next(nullptr)
		,_data(data)
	{}
};
//封装一个迭代器
template<class T, class Ref, class Ptr> 
struct __list_iterator
{
	typedef ListNode<T> Node;
	typedef __list_iterator<T, Ref, Ptr> self; //一个迭代器对象

	typedef Ref reference;
	typedef Ptr pointer;
	Node* _node;

	//it2 = it1 浅拷贝 -->假设是深拷贝,这从某种意义上又搞了一个链表,这样就乱套了
	//拷贝构造和赋值重载不需要我们自己实现
	//析构呢? ->迭代器是借助结点的指针访问修改链表
	//结点属于链表,不属于迭代器,所以这里不用管释放
	__list_iterator(Node*x)
		:_node(x)
	{}
	Ref operator*()
	{
		return _node->_data;
	}
	Ptr operator->()
	{
		return &_node->_data;
	}
	//++it
	self& operator++()
	{
		_node = _node->_next;
		return *this;
	}
	//it++
	self operator++(int)
	{
		self tmp(*this);
		_node = _node->_next;
		return tmp;
	}
	//--it
	self& operator--()
	{
		_node = _node->_prev;
		return *this;
	}
	//it--
	self operator--(int)
	{
		self tmp(*this); //先构造一个临时对象
		_node = _node->_prev;
		return tmp;
	}
	//重载两个迭代器的比较
	bool operator != (const self& it) const
	{
		return _node != it._node;
	}
	bool operator == (const self& it) const
	{
		return _node == it._node;
	}
};

template<class T>
class list
{
	typedef ListNode<T> Node;
public:
	typedef __list_iterator<T, T&, T*> iterator;
	typedef __list_iterator<T, const T&, const T*> const_iterator; //第一个T是表示类型,不加const

	typedef reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;
	typedef reverse_iterator<iterator, T&, T*> reverse_iterator;

	reverse_iterator rbegin()
	{
		return reverse_iterator(end());
	}
	reverse_iterator rend()
	{
		return reverse_iterator(begin());
	}

	iterator begin()
	{
		return iterator(_head->_next); //Node*
	}
	iterator end()
	{
		return iterator(_head); //Node*
	}
	const_iterator begin() const //不加const会冲突,下面也一样
	{
		return const_iterator(_head->_next);
	}
	const_iterator end() const
	{
		return const_iterator(_head);
	}
	list() //初始化,构造一个头结点
	{
		_head = new Node();
		_head->_next = _head;
		_head->_prev = _head;
	}

	//<Date>  <int> 决定了后面数据类型
	// list<Date> lt1(5, Date(2022,4,12));
	// list<int> lt2(5, 1);
	//如果只实现一个size_t的版本上面两个可能存在参数匹配问题。
		// (5, Date(2022,4,12)) int/size_t  Date
	// list<int> lt2(5, 1) int int比(size_t int)更匹配,于是走InputIterator那个地方了,
	//整数1被解引用后就会报错
	list(size_t n, const T& val = T())
	{
		_head = new Node; //加不加括号都可以
		_head->_next = _head;
		_head->_prev = _head;
		for (size_t i = 0; i < n; i++)
		{
			push_back(val);
		}
	}
	list(int n, const T& val = T())
	{
		_head = new Node; //加不加括号都可以
		_head->_next = _head;
		_head->_prev = _head;
		for (int i = 0; i < n; i++)
		{
			push_back(val);
		}
	}
	template<class InputIterator>
	list(InputIterator first, InputIterator last)
	{
		_head = new Node();
		_head->_next = _head;
		_head->_prev = _head;
		while (first != last)
		{
			push_back(*first);
			first++;
		}
	}
	//lt2(lt1)
	//拷贝构造也是构造函数,调用拷贝构造构造函数就不会主动调用了
	list(const list<T>& lt) 
	{
		//先初始化
		_head = new Node();
		_head->_next = _head;
		_head->_prev = _head;

		list<T> tmp(lt.begin(), lt.end()); //复用构造函数
		std::swap(_head, tmp._head);
	}
	//lt2=lt1
	list<T>& operator=(list<T> lt) //复用拷贝构造
	{
		std::swap(_head, lt._head);
		return *this;
	}

	//方法二:传统写法
	//lt2(lt1)
	//list(const list<T>& lt)
	//{
	//	//先初始化
	//	_head = new Node();
	//	_head->_next = _head;
	//	_head->_prev = _head;
	//	
	//	for (auto e : it)
	//	{
	//		push_back(e);
	//	}
	//}
	lt2=lt1
	//list<T>& operator=(list<T>& lt) 
	//{
	//	if (this != &lt) //不能上来就清空!!
	//	{
	//		clear();
	//		for (auto e : lt)
	//		{
	//			push_back(e);
	//		}
	//	}
	//	return *this;
	//}
	~list()
	{
		clear();
		delete _head;
		_head = nullptr;
	}
	void clear()
	{
		iterator it = begin();
		while (it != end())
		{
			iterator del = it++;
			delete del._node; //_node是在list类中new出来的
		}
		//清理完节点后重新链接头结点关系
		_head->_next = _head;
		_head->_prev = _head;

		//iterator it = begin();
		//while (it != end())
		//{
		//	erase(it++); //这里不能分开写
		//}
	}
	void push_front(const T& x)
	{
		insert(begin(), x);
	}
	void pop_front()
	{
		erase(begin());
	}
	void push_back(const T& x)
	{
		insert(end(), x);//end()不能给成_head,这里是一个迭代器
	}
	void pop_back()
	{
		erase(--end());
	}
	iterator insert(iterator pos, const T& x)
	{
		Node* prev = pos._node->_prev;
		Node* cur = pos._node;
		Node* newnode = new Node(x);

		prev->_next = newnode;
		newnode->_prev = prev;
		newnode->_next = cur;
		cur->_prev = newnode;
		return iterator(newnode);
	}
	//erase之后,it就失效了
	iterator erase(iterator pos)
	{
		assert(pos != end()); //头结点不能删
		Node* prev = pos._node->_prev;
		Node* next = pos._node->_next;
		prev->_next = next;
		next->_prev = prev;

		delete pos._node;
		return iterator(next);
	}
private:
	Node* _head;
	};
}

reverse_iterator.h

#pragma once

namespace cyq
{
	//适配器

	//Iterator是哪个容器的迭代器,reverse_iterator<Iterator>就可以
	//适配出哪个容器的反向迭代器,复用的体现
	template<class Iterator,class Ref,class Ptr>
	class reverse_iterator
	{
	typedef reverse_iterator<Iterator, Ref, Ptr> self;
public:

	reverse_iterator(Iterator it)
		:_it(it)
	{}
	// 1、这时候Iterator还没有实例化,还没法使用::,这时候需要使用typename提前告知有这个类型
	typename Iterator::reference operator*()
	{
		Iterator prev = _it;
		return *--prev;
	}
	//2、
	//Ref operator*()
	//{
	//	Iterator prev = _it;
	//	return *--prev;
	//}
	// 1、这时候Iterator还没有实例化,还没法使用::,这时候需要使用typename提前告知有这个类型
	typename Iterator::pointer operator->()
	{
		return &operator*();
	}
	//2、
	/*Ptr operator->()
	{
		return &operator*();
	}*/
	self& operator++()
	{
		--_it;
		return *this;
	}
	self operator++(int)
	{
		self tmp(*this);
		--_it;
		return tmp;
	}
	self& operator--()
	{
		++_it;
		return *this;
	}
	self operator--(int)
	{
		self tmp(*this);
		++_it;
		return tmp;
	}
	bool operator!=(const self& rit) const
	{
		return _it != rit._it;
	}
	bool operator==(const self& rit) const
	{
		return _it == rit._it;
	}
private:
	Iterator _it;
};
}

测试代码

struct Date
{
	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{}
	int _year;
	int _month;
	int _day;
};

void test_list()
{
	cyq::list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_front(10);
	lt.push_front(20);
	lt.push_front(30);
	cyq::list<int>::iterator it = lt.begin();
	while (it != lt.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;

	lt.pop_back();
	lt.pop_front();
    it = lt.begin();
	while (it != lt.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;

	cyq::list<int> lt2(5, 10);
	for (auto e : lt2)
	{
		cout << e << " ";
	}
	cout << endl;

	cyq::list<Date> lt3(5, Date(2022,4,13));
	auto it3 = lt3.begin();
	while (it3 != lt3.end())
	{
		cout << it3->_year << "/" << it3->_month << "/" << it3->_day << endl;
		it3++;
	}
	//for (auto e : lt3)
	//{
	//	cout << e << endl;
	//}
	cout << endl;

	auto it4 = lt2.rbegin();
	while (it4 != lt2.rend())
	{
		cout << *it4 << " ";
		it4++;
	}
	cout << endl;
}
int main()
{
	test_list();

	return 0;
}

测试结果:

       博主觉得之前的模拟实现容器的博客和这篇博客很相似,所以有些地方写的比较简略,相信大家也能看懂的~

        如果大家又不懂得地方欢迎来私信我~

       list模拟实现难点主要是容器适配器和类与类之间的反复调用,如果大家看得有些吃力,可能C++类和对象的知识有些不足,老铁们可以看一下我曾经写的关于类和对象的博客。

看到这里,希望大家支持下~

       

猜你喜欢

转载自blog.csdn.net/qq_58724706/article/details/124359372