【C++STL】list的反向迭代器

简介: 【C++STL】list的反向迭代器

image.png


reverse.h

#pragma once
namespace mudan
{
  template<class Iterator, class Ref, class Ptr>
  struct __reverse_iterator
  {
  Iterator _cur;
  typedef __reverse_iterator<Iterator, Ref, Ptr> RIterator;
  __reverse_iterator(Iterator it)
    :_cur(it)
  {}
  RIterator operator++()
  {
    --_cur;
    return *this;
  }
  RIterator operator--()
  {
    ++_cur;
    return *this;
  }
  Ref operator*()
  {
    //return *_cur;
    auto tmp = _cur;
    --tmp;
    return *tmp;
  }
  Ptr operator->()
  {
    //return _cur.operator->();
    return &(operator*());
  }
  bool operator!=(const RIterator& it)
  {
    return _cur != it._cur;
  }
  };
}

list.h

#include<assert.h>
#include<iostream>
#include<algorithm>
#include"reverse.h"   
using namespace std;
namespace mudan
{
  template<class T>
  struct list_node
  {
  T _data;
  list_node<T>* _next;
  list_node<T>* _prev;
  list_node(const T& x = T())
    :_data(x)
    , _next(nullptr)
    , _prev(nullptr)
  {}
  };
  // typedef __list_iterator<T, T&, T*>             iterator;
  // typedef __list_iterator<T, const T&, const T*> const_iterator;
  // 像指针一样的对象
  template<class T, class Ref, class Ptr>
  struct __list_iterator
  {
  typedef list_node<T> Node;
  typedef __list_iterator<T, Ref, Ptr> iterator;
  typedef bidirectional_iterator_tag iterator_category;
  typedef T value_type;
  typedef Ptr pointer;
  typedef Ref reference;
  typedef ptrdiff_t difference_type;
  Node* _node;
  __list_iterator(Node* node)
    :_node(node)
  {}
  bool operator!=(const iterator& it) const
  {
    return _node != it._node;
  }
  bool operator==(const iterator& it) const
  {
    return _node == it._node;
  }
  // *it  it.operator*()
  // const T& operator*()
  // T& operator*()
  Ref operator*()
  {
    return _node->_data;
  }
  //T* operator->() 
  Ptr operator->()
  {
    return &(operator*());
  }
  // ++it
  iterator& operator++()
  {
    _node = _node->_next;
    return *this;
  }
  // it++
  iterator operator++(int)
  {
    iterator tmp(*this);
    _node = _node->_next;
    return tmp;
  }
  // --it
  iterator& operator--()
  {
    _node = _node->_prev;
    return *this;
  }
  // it--
  iterator operator--(int)
  {
    iterator tmp(*this);
    _node = _node->_prev;
    return tmp;
  }
  };
  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 __reverse_iterator<iterator, T&, T*> reverse_iterator;
  typedef __reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;
  const_iterator begin() const
  {
    return const_iterator(_head->_next);
  }
  const_iterator end() const
  {
    return const_iterator(_head);
  }
  iterator begin()
  {
    return iterator(_head->_next);
  }
  iterator end()
  {
    return iterator(_head);
  }
  reverse_iterator rbegin()
  {
    return reverse_iterator(end());
  }
  reverse_iterator rend()
  {
    return reverse_iterator(begin());
  }
  void empty_init()
  {
    // 创建并初始化哨兵位头结点
    _head = new Node;
    _head->_next = _head;
    _head->_prev = _head;
  }
  template <class InputIterator>
  list(InputIterator first, InputIterator last)
  {
    empty_init();
    while (first != last)
    {
    push_back(*first);
    ++first;
    }
  }
  list()
  {
    empty_init();
  }
  void swap(list<T>& x)
    //void swap(list& x)
  {
    std::swap(_head, x._head);
  }
  // lt2(lt1)
  list(const list<T>& lt)
  {
    empty_init();
    list<T> tmp(lt.begin(), lt.end());
    swap(tmp);
  }
  // lt1 = lt3
  list<T>& operator=(list<T> lt)
  {
    swap(lt);
    return *this;
  }
  ~list()
  {
    clear();
    delete _head;
    _head = nullptr;
  }
  void clear()
  {
    iterator it = begin();
    while (it != end())
    {
    it = erase(it);
    }
  }
  void push_back(const T& x)
  {
    //Node* tail = _head->_prev;
    //Node* newnode = new Node(x);
    _head          tail  newnode
    //tail->_next = newnode;
    //newnode->_prev = tail;
    //newnode->_next = _head;
    //_head->_prev = newnode;
    insert(end(), x);
  }
  void push_front(const T& x)
  {
    insert(begin(), x);
  }
  iterator insert(iterator pos, const T& x)
  {
    Node* cur = pos._node;
    Node* prev = cur->_prev;
    Node* newnode = new Node(x);
    // prev newnode cur
    prev->_next = newnode;
    newnode->_prev = prev;
    newnode->_next = cur;
    cur->_prev = newnode;
    return iterator(newnode);
  }
  void pop_back()
  {
    erase(--end());
  }
  void pop_front()
  {
    erase(begin());
  }
  iterator erase(iterator pos)
  {
    assert(pos != end());
    Node* cur = pos._node;
    Node* prev = cur->_prev;
    Node* next = cur->_next;
    prev->_next = next;
    next->_prev = prev;
    delete cur;
    return iterator(next);
  }
  private:
  Node* _head;
  };
  void test()
  {
  list<int> ls;
  ls.push_back(1);
  ls.push_back(2);
  ls.push_back(3);
  ls.push_back(4);
  ls.push_back(5);
  ls.push_back(6);
  for (auto& e : ls)
  {
    cout << e << " ";
  }
  cout << endl;
  list<int>copy = ls;
  for (auto e : copy)
  {
    cout << e << " ";
  }
  }
}

test.cpp

#include"list.h"
#include<list>
int main(void)
{
  mudan::test();
  //list<int>ls;
  //ls.push_back(1);
  //ls.push_back(2);
  //ls.push_back(3);
  //ls.push_back(4);
  //ls.push_back(5);
  //ls.push_back(6);
  //for (auto e : ls)
  //{
  //  cout << e << " ";
  //}
  //cout << endl;
  //list<int>lt(ls);
  //for (auto e : lt)
  //{
  //  cout << e << " ";
  //}
  return 0;
}

疑问1:为什么在迭代器当中不需要写深拷贝、析构函数

1、因为迭代器就是希望做到浅拷贝,就是需要拿到地址而不是值,因为迭代器的修改是会影响对象中的内容的


2、因为迭代器并没有申请额外的空间,所以不需要析构,如果写了析构函数,那么调用一次迭代器那岂不是把对象都给销毁了😂😂😂


疑问2:为什么在迭代器当中需要三个模板参数?

其实这三个参数是被抽象出来的,__list_iterator等价于__list_iterator,其实在迭代器当中只有一个参数也可以正常推导,但是在list类当中只有一个参数就不行了,因为如果传递过来的是const修饰的类,然后用T&来接收的话会导致权限被缩小了,所以,为了解决这个const的问题,直接显示的定义模板参数*


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


Ref就是reference


Ptr就是pointer


疑问3:反向迭代器是怎么实现的?

反向迭代器其实就是利用正向迭代器实现的,重载一下++、–等操作符,不过逻辑上功能要反过来写


疑问4:为什么*解引用不直接返回当前值

image.png


因为begin()和end()的位置和正常实现的不一样


image.png


为什么要加一些不认识的typedef

typedef bidirectional_iterator_tag iterator_category;
  typedef T value_type;
  typedef Ptr pointer;
  typedef Ref reference;
  typedef ptrdiff_t difference_type;
目录
相关文章
|
1月前
|
存储 程序员 C++
C++常用基础知识—STL库(2)
C++常用基础知识—STL库(2)
69 5
|
1月前
|
存储 算法 C++
【C++打怪之路Lv10】-- list
【C++打怪之路Lv10】-- list
21 1
|
1月前
|
存储 自然语言处理 程序员
C++常用基础知识—STL库(1)
C++常用基础知识—STL库(1)
52 1
|
1月前
|
算法 安全 Linux
【C++STL简介】——我与C++的不解之缘(八)
【C++STL简介】——我与C++的不解之缘(八)
|
1月前
|
算法 数据处理 C++
c++ STL划分算法;partition()、partition_copy()、stable_partition()、partition_point()详解
这些算法是C++ STL中处理和组织数据的强大工具,能够高效地实现复杂的数据处理逻辑。理解它们的差异和应用场景,将有助于编写更加高效和清晰的C++代码。
23 0
|
5月前
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
934 1
|
4月前
|
Java API Apache
怎么在在 Java 中对List进行分区
本文介绍了如何将列表拆分为给定大小的子列表。尽管标准Java集合API未直接支持此功能,但Guava和Apache Commons Collections提供了相关API。
|
4月前
|
运维 关系型数据库 Java
PolarDB产品使用问题之使用List或Range分区表时,Java代码是否需要进行改动
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
4月前
|
存储 安全 Java
详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法
详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法
|
5月前
|
Java API
使用 Java 来实现两个 List 的差集操作
使用 Java 来实现两个 List 的差集操作
149 3

热门文章

最新文章

下一篇
无影云桌面