【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;
目录
相关文章
|
5天前
|
编译器 C语言 C++
【c++丨STL】list模拟实现(附源码)
本文介绍了如何模拟实现C++中的`list`容器。`list`底层采用双向带头循环链表结构,相较于`vector`和`string`更为复杂。文章首先回顾了`list`的基本结构和常用接口,然后详细讲解了节点、迭代器及容器的实现过程。 最终,通过这些步骤,我们成功模拟实现了`list`容器的功能。文章最后提供了完整的代码实现,并简要总结了实现过程中的关键点。 如果你对双向链表或`list`的底层实现感兴趣,建议先掌握相关基础知识后再阅读本文,以便更好地理解内容。
14 1
|
17天前
|
算法 C语言 C++
【c++丨STL】list的使用
本文介绍了STL容器`list`的使用方法及其主要功能。`list`是一种双向链表结构,适用于频繁的插入和删除操作。文章详细讲解了`list`的构造函数、析构函数、赋值重载、迭代器、容量接口、元素访问接口、增删查改操作以及一些特有的操作接口如`splice`、`remove_if`、`unique`、`merge`、`sort`和`reverse`。通过示例代码,读者可以更好地理解如何使用这些接口。最后,作者总结了`list`的特点和适用场景,并预告了后续关于`list`模拟实现的文章。
33 7
|
2月前
|
存储 编译器 C语言
【c++丨STL】vector的使用
本文介绍了C++ STL中的`vector`容器,包括其基本概念、主要接口及其使用方法。`vector`是一种动态数组,能够根据需要自动调整大小,提供了丰富的操作接口,如增删查改等。文章详细解释了`vector`的构造函数、赋值运算符、容量接口、迭代器接口、元素访问接口以及一些常用的增删操作函数。最后,还展示了如何使用`vector`创建字符串数组,体现了`vector`在实际编程中的灵活性和实用性。
64 4
|
20天前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
30 0
|
7月前
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
1064 1
|
6月前
|
Java API Apache
怎么在在 Java 中对List进行分区
本文介绍了如何将列表拆分为给定大小的子列表。尽管标准Java集合API未直接支持此功能,但Guava和Apache Commons Collections提供了相关API。
|
6月前
|
运维 关系型数据库 Java
PolarDB产品使用问题之使用List或Range分区表时,Java代码是否需要进行改动
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
6月前
|
存储 安全 Java
详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法
详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法
|
7月前
|
Java API
使用 Java 来实现两个 List 的差集操作
使用 Java 来实现两个 List 的差集操作
220 3
|
6月前
|
存储 Java 索引
Java List接口实现原理与性能评估
Java List接口实现原理与性能评估