【十五】【C++】list的简单实现

list 的迭代器解引用探究

 
/*list的迭代器解引用探究*/
#if 1
#include <list>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

class Date {
    private:
        int _year;
        int _month;
        int _day;
    public:
        Date()
            : _year(2024)
            , _month(1)
            , _day(1)
        {}

        void Show() {
            cout << _year << "-" << _month << "-" << _day << endl;
        }
 };
void TestList8() {
    list<Date> L1;
    L1.push_back(Date());
    L1.push_back(Date());
    L1.push_back(Date());
    L1.push_back(Date());
    
     auto it1=L1.begin();
    while(it1!=L1.end()){
        it1->Show();
        it1++;
    }
    
     list<int> L2;
    L2.push_back(1);
    L2.push_back(2);
    L2.push_back(3);
    L2.push_back(4);
    
     auto it2=L2.begin();
    while(it2!=L2.end()){
        cout<<*it2<<endl;
        it2++;
    }
 }

int main() {
    TestList8();
 }
#endif

这段代码主要展示了如何在 C++ 中使用 std::list 容器来存储和遍历自定义类型(Date 类)的对象以及基本数据类型(int)的值。程序定义了一个 Date 类,用于表示日期,并提供了一个 Show 成员函数来打印日期。然后,它在函数 TestList8 中创建了两个 std::list 容器:一个存储 Date 对象,另一个存储 int 值。通过迭代器遍历这些列表,并展示了如何访问和操作容器中的元素。

这段代码看似平平无奇,细心的小伙伴可能会发现,在遍历L1list对象的时候,it1->Show();这一行代码似乎有一点问题。it1迭代器底层是list结点的指针,it1->得到的结果应该是Date类型对象而不能直接访问Date类型对象的成员才对。如果it1底层指针存储的是节点中Date类型的对象的地址,那么it1->Show();就没有任何问题。

实际上list类中->底层会返回*it迭代器的地址,Ptr operator->(){return &(operator*()); },但即使返回了地址,我们还需要一个->才能访问Date的对象才对。正确的做法就变成了it1->->Show();这个样子。但是这样的代码可读性太差了,为了提高代码的可读性,编译器自动给我们添加一个->,使得我们仅仅使用it1->Show();这样的代码就可以完成实现。

代码实现

 
#include<iostream>
using namespace std;
#include<algorithm>
namespace Mylist
{
    template<class T>
    struct ListNode
    {
        ListNode<T>* _next;
        ListNode<T>* _prev;
        T _value;
        
         ListNode(const T& value = T())
        : _next(nullptr)
        , _prev(nullptr)
        , _value(value)
        {}
    };
    
     // 1. 封装迭代器对应的类
    template<class T, class Ref, class Ptr>
    struct ListIterator
    {
        typedef ListNode<T> Node;
        typedef Ref ItRef;
        typedef Ptr ItPtr;
        
         typedef ListIterator<T, Ref, Ptr> Self;
    public:
        ListIterator(Node* pNode = nullptr)
        : _pNode(pNode)
        {}
        
         //
        // 具有指针类似的操作
        Ref operator*()
        {
            return _pNode->_value;
        }
        
         Ptr operator->()
        {
            return &(operator*());
        }
        
         
        // 移动
        Self& operator++()
        {
            _pNode = _pNode->_next;
            return *this;
        }
        
         Self operator++(int)
        {
            Self temp(*this);
            _pNode = _pNode->_next;
            return temp;
        }
        
         Self& operator--()
        {
            _pNode = _pNode->_prev;
            return *this;
        }
        
         Self operator--(int)
        {
            Self temp(*this);
            _pNode = _pNode->_prev;
            return temp;
        }
        
         ///
        // 比较
        bool operator!=(const Self& s)const
        {
            return _pNode != s._pNode;
        }
        
         bool operator==(const Self& s)const
        {
            return _pNode == s._pNode;
        }
        
         Node* _pNode;
    };
    
     
     // 反向迭代器:就是对正向迭代器的包装
    template<class Iterator>
    struct ListReverseIterator
    {
        // 静态成员变量也可以通过类名::静态成员变量名称
        // typedef Iterator::ItRef Ref;  编译报错
        // 编译器无法在编译时无法确定ItRef是静态成员变量 还是 类型
        // 需要显式告诉编译器ItRef就是Iterator类中的类型
        // typename
        typedef typename Iterator::ItRef Ref;
        typedef typename Iterator::ItPtr Ptr;
        typedef ListReverseIterator<Iterator> Self;
    public:
        ListReverseIterator(Iterator it)
        : _it(it)
        {}
        
         Ref operator*()
        {
            Iterator temp(_it);
            --temp;
            return *temp;
        }
        
         Ptr operator->()
        {
            return &(operator*());
        }
        
         Self& operator++()
        {
            --_it;
            return *this;
        }
        
         Self operator++(int)
        {
            Self temp(*this);
            --_it;
            return temp;
        }
        
         Self& operator--()
        {
            ++_it;
            return *this;
        }
        
         Self operator--(int)
        {
            Self temp(*this);
            ++_it;
            return temp;
        }
        
         bool operator!=(const Self& rit)const
        {
            return _it != rit._it;
        }
        
         bool operator==(const Self& rit)const
        {
            return _it == rit._it;
        }
        
         Iterator _it;
    };
    
     template<class T>
    class list
    {
        typedef ListNode<T> Node;
        
         // 2. 在容器中给迭代器类型取别名---public
    public:
        typedef ListIterator<T, T&, T*> iterator;
        typedef ListIterator<T, const T&, const T*> const_iterator;
        
        typedef ListReverseIterator<iterator> reverse_iterator;
        typedef ListReverseIterator<const_iterator> const_reverse_iterator;
    public:
        // 注意:list的迭代器一定不能是原生态的指针
        // vector之所以可以,因为vector底层是连续空间
        // 如果指针指向连续的空间,对指针++/--,该指针就可以移动到下一个/前一个位置
        // 但是list不行,因为链表中的节点是通过next和prev指针组织起来的,不一定连续
        // 如果将list的迭代器设置为原生态指针,++it/--it没有意义
        // typedef Node* iterator;  // ???
        
     public:
        
        // 构造
        list()
        {
            CreateHead();
        }
        
         list(int n, const T& value = T())
        {
            CreateHead();
            for (int i = 0; i < n; ++i)
            {
                push_back(value);
            }
        }
        
         template<class Iterator>
        list(Iterator first, Iterator last)
        {
            CreateHead();
            while (first != last)
            {
                push_back(*first);
                ++first;
            }
        }
        
         list(const list<T>& L)
        {
            CreateHead();
            auto it = L.cbegin();
            while (it != L.cend())
            {
                push_back(*it);
                ++it;
            }
        }
        
         list<T>& operator=(list<T> L)
        {
            this->swap(L);
            return *this;
        }
        
         ~list()
        {
            clear();
            delete _head;
            _head = nullptr;
        }
        
         //
        // 迭代器
        // 3. 增加begin和end的方法
        iterator begin()
        {
            /*iterator ret(_head->_next);
            return ret;*/
            
             return iterator(_head->_next);
        }
        
         iterator end()
        {
            return iterator(_head);
        }
        
         const_iterator cbegin()const
        {
            /*iterator ret(_head->_next);
            return ret;*/
            
             return const_iterator(_head->_next);
        }
        
         const_iterator cend()const
        {
            return const_iterator(_head);
        }
        
         reverse_iterator rbegin()
        {
            return reverse_iterator(end());
        }
        
         reverse_iterator rend()
        {
            return reverse_iterator(begin());
        }
        
         const_reverse_iterator crbegin()const
        {
            return const_reverse_iterator(cend());
        }
        
         const_reverse_iterator crend()const
        {
            return const_reve
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

妖精七七_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值