从C语言到C++_20(仿函数+优先级队列priority_queue的模拟实现+反向迭代器)(下)

简介: 从C语言到C++_20(仿函数+优先级队列priority_queue的模拟实现+反向迭代器)

从C语言到C++_20(仿函数+优先级队列priority_queue的模拟实现+反向迭代器)(上):https://developer.aliyun.com/article/1521891

2. 反向迭代器

(此篇文章加上代码两万多字,可以在这分两部分看了)

前面讲 list 我们没实现反向迭代器,计划放在这里讲,反向迭代器怎么实现呢,

反向迭代器和正向迭代器加加的方向不一样(唯一区别)。

(即正向迭代器 ++ 是向后走,反向迭代器 ++ 是向前走)

正常思维是把正向迭代器复制粘贴一份,把 ++ 改成 -- 啥的,

前面讲了容器适配器,大佬就实现了一个迭代器适配器:

库里的反向迭代器其实就是对正向迭代器的一种封装 —— 适配器模式(配接器模式)

用传过来的正向迭代器实现反向迭代器,直接建一个reverse_iterator.h。


2.1 反向迭代器的普通实现

如果知道反向迭代器其实就是对正向迭代器的一种封装 ,因为以前认为rbegin()指向的是最后一个数据,rend()指向的是第一个数据的前一个(哨兵位头结点)(库里面不是的)

所以现在普通思路实现出来是这样的:(虽然库里面不是的,但也可以实现出来)

reverse_iterator.h(不对称版)

#pragma once
 
namespace rtx
{
  template<class Iterator, class Ref, class Ptr>// 为了适配const迭代器,再加两个参数
  struct __reverse_iterator  //普通迭代器传的就是 T& 和 T*  const 迭代器传的就是 const T& 和 const T* 
  {
    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;
    }
 
    Ptr operator->()
    {
      //return _cur.operator->();
      //return &(*_cur); // 如果这样写,对称的时候就要改了
      return &(operator*());
    }
 
    bool operator!=(const RIterator& it)
    {
      return _cur != it._cur;
    }
  };
}

如果 vector 需要反向迭代器,那就把 vector 的正向迭代器传给 Iterator,

它就可以通过正向迭代器转换出 vector 的反向迭代器。

也就是说,我们实现的反向迭代器并包装的这个类,不是针对某个容器而是针对所有容器的。

任何一个容器只要你实现了正向迭代器,就可以通过其适配出反向迭代器。

先拿list.h 试一下,包一下头文件"reverse_iterator.h",在以前实现的 list类 加上了下面的代码

    typedef __reverse_iterator<iterator, T&, T*> reverse_iterator; // 传正向迭代器封装出反向迭代器
    typedef __reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;
  
      reverse_iterator rbegin()//按照以前的理解,rbegin指向最后一个数据
    {
      //return reverse_iterator(_head->_prev);
      return reverse_iterator(--end());
    }
    reverse_iterator rend()//按照以前的理解,rend指向第一个数据前一个(哨兵位)
    {
      //return reverse_iterator(_head);
      return reverse_iterator(end());
    }
 
    const_reverse_iterator rbegin() const
    {
      //return const_reverse_iterator(_head->_prev);
      return const_reverse_iterator(--end());
    }
    const_reverse_iterator rend() const
    {
      //return const_reverse_iterator(_head);
      return const_reverse_iterator(end());
    }

现在的 list.h 就是这样的:

#pragma once
 
#include<iostream>
#include<assert.h>
#include "reverse_iterator.h"
using namespace std;
 
namespace rtx
{
  template<class T>
  struct list_node // 定义结点
  {
    T _data;
    list_node* _prev;
    list_node* _next;
 
    list_node(const T& x = T())
      :_data(x)
      ,_prev(nullptr)
      ,_next(nullptr)
    {}
  };
 
  template<class T, class Ref, class Ptr>
  struct __list_iterator // 定义迭代器
  {
    typedef list_node<T> Node;
    typedef __list_iterator<T, Ref, Ptr> iterator;
    // 在list类里面:
    // typedef __list_iterator<T, T&, T*>             iterator;
        // typedef __list_iterator<T, const T&, const T*> const_iterator;
    Node* _node;
 
    __list_iterator(Node* node)
      :_node(node)
    {}
 
    bool operator!=(const iterator& it)
    {
      return _node != it._node;
    }
    //T& operator*()
    Ref operator*()
    {
      return _node->_data;  // 返回结点的数据
    }
    //T* operator->()
    Ptr operator->()
    {
      return &(operator*());
      //即 return &(_node->_data);
    }
    iterator& operator++()
    {
      _node = _node->_next;
      return *this; // 返回加加后的值
    }
    iterator operator++(int)
    {
      iterator tmp(*this); // 拷贝构造一个tmp存储原来的值
      _node = _node->_next;
      return tmp; // 返回加加前的值
    }
    iterator& operator--()
    {
      _node = _node->_prev;
      return *this; // 返回减减后的值
    }
    iterator operator--(int)
    {
      iterator tmp(*this); // 拷贝构造一个tmp存储原来的值
      _node = _node->prev;
      return tmp; // 返回减减前的值
    }
  };
 
  template<class T>
  class list // 定义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()// begin是实际数据的第一个,_head 是哨兵位头结点
    {
      return iterator(_head->_next);
    }
    iterator end()// end是实际数据的下一个
    {
      return iterator(_head);
    }
 
    reverse_iterator rbegin()//按照以前的理解,rbegin指向最后一个数据
    {
      //return reverse_iterator(_head->_prev);
      return reverse_iterator(--end());
    }
    reverse_iterator rend()//按照以前的理解,rend指向第一个数据前一个(哨兵位)
    {
      //return reverse_iterator(_head);
      return reverse_iterator(end());
    }
 
    const_reverse_iterator rbegin() const
    {
      //return const_reverse_iterator(_head->_prev);
      return const_reverse_iterator(--end());
    }
    const_reverse_iterator rend() const
    {
      //return const_reverse_iterator(_head);
      return const_reverse_iterator(end());
    }
 
    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)也行(类里面可以省略<T>,类外不行>
    {
      std::swap(_head, x._head); // 换哨兵位头结点就行
    }
 
    list(const list<T>& lt)//lt2(lt1)
    {
      empty_init();
      list<T> tmp(lt.begin(), lt.end()); // 迭代器区间构造一个(lt1)
      swap(tmp); // 直接和lt2换哨兵位头结点
    }
    list<T>& operator=(list<T> lt)//lt3 = lt1 这里lt1直接深拷贝给lt,lt是局部对象,出来作用域直接调析构
    {
      swap(lt);// 把深拷贝出来的lt和lt3交换
      return *this; // 把lt3返回
    }
 
    ~list()
    {
      clear();
      delete _head;
      _head = nullptr;
    }
    void clear()
    {
      iterator it = begin();
      while (it != end())
      {
        it = erase(it); // 返回删除位置的下一个结点
      }
    }
 
    iterator insert(iterator pos, const T& x)
    {
      Node* cur = pos._node;
      Node* prev = cur->_prev;
      Node* NewNode = new Node(x);
 
      prev->_next = NewNode;
      NewNode->_prev = prev;
      NewNode->_next = cur;
      cur->_prev = NewNode;
 
      return iterator(NewNode);
    }
    void push_back(const T& x)
    {
      //Node* tail = _head->_prev;
      //Node* NewNode = new Node(x);
       思路图:head        tail  NewNode
      //tail->_next = NewNode;
      //NewNode->_prev = tail;
      //_head->_prev = NewNode;
      //NewNode->_next = _head;
      insert(end(), x);
    }
    void push_front(const T& x)
    {
      insert(begin(), x);
    }
 
    iterator erase(iterator pos)
    {
      assert(pos != end());
      Node* cur = pos._node; // 删cur
      Node* prev = cur->_prev;
 
      prev->_next = cur->_next; // cur前一个指向cur后一个
      cur->_next->_prev = prev; // cur后一个指回cur前一个
 
      delete cur;
      return iterator(prev->_next); // 返回删除位置下一个
    }
    void pop_back()
    {
      erase(begin());
    }
    void pop_front()
    {
      erase(--end());
    }
 
  private:
    Node* _head; // 哨兵位头结点
  };
}

测试一下:

#define _CRT_SECURE_NO_WARNINGS 1
 
#include "list.h"
 
namespace rtx
{
  void Test_reverse_iterator()
  {
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);
    lt.push_back(5);
 
    list<int>::iterator it = lt.begin();
    while (it != lt.end())
    {
      cout << *it << " ";
      ++it;
    }
    cout << endl;
 
    list<int>::reverse_iterator rit = lt.rbegin();
    while (rit != lt.rend())
    {
      cout << *rit << " ";
      ++rit;
    }
    cout << endl;
  }
}
 
int main()
{
  rtx::Test_reverse_iterator();
 
  return 0;
}

测试一下:

#define _CRT_SECURE_NO_WARNINGS 1
 
#include "list.h"
 
namespace rtx
{
  void Test_reverse_iterator()
  {
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);
    lt.push_back(5);
 
    list<int>::iterator it = lt.begin();
    while (it != lt.end())
    {
      cout << *it << " ";
      ++it;
    }
    cout << endl;
 
    list<int>::reverse_iterator rit = lt.rbegin();
    while (rit != lt.rend())
    {
      cout << *rit << " ";
      ++rit;
    }
    cout << endl;
  }
}
 
int main()
{
  rtx::Test_reverse_iterator();
 
  return 0;
}

这样实现也行,但是rbegin()和rend()就没那么美观,

所以巨佬就设计了下面的艺术行为:(也只是为了对称,没别的)


2.2 反向迭代器的对称实现

前面说到,我们认为应该是这样的:


但是库里面是这样实现的:

rbegin 和 rend 是和 end 和 begin 是相对称的形式设计的,

你的 end 就是我的 rbegin,你的 begin 就是我的 rend。

如果这样实现的话,对rbegin解引用就不对了,

我们先看看库里反向迭代器的解引用:

这样取的就是前一个位置了,rbegin() 位置的前一个位置正是想要取的地方。

来改一下,解引用应该是这样的:

    reverse_iterator rbegin()// 对称实现
    {
      //return reverse_iterator(_head->_prev);
      //return reverse_iterator(--end());
      return reverse_iterator(end());
    }
    reverse_iterator rend()
    {
      //return reverse_iterator(_head);
      //return reverse_iterator(end());
      return reverse_iterator(begin());
    }
 
    const_reverse_iterator rbegin() const
    {
      //return const_reverse_iterator(_head->_prev);
      return const_reverse_iterator(end());
    }
    const_reverse_iterator rend() const
    {
      //return const_reverse_iterator(_head);
      return const_reverse_iterator(begin());
    }


reverse_iterator.h

#pragma once
 
namespace rtx
{
  template<class Iterator, class Ref, class Ptr>// 为了适配const迭代器,再加两个参数
  struct __reverse_iterator  //普通迭代器传的就是 T& 和 T*  const 迭代器传的就是 const T& 和 const T* 
  {
    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 &(*_cur); // 如果这样写,对称的时候就要改了
      return &(operator*());
    }
 
    bool operator!=(const RIterator& it)
    {
      return _cur != it._cur;
    }
  };
}

list.h :

#pragma once
 
#include<iostream>
#include<assert.h>
#include "reverse_iterator.h"
using namespace std;
 
namespace rtx
{
  template<class T>
  struct list_node // 定义结点
  {
    T _data;
    list_node* _prev;
    list_node* _next;
 
    list_node(const T& x = T())
      :_data(x)
      ,_prev(nullptr)
      ,_next(nullptr)
    {}
  };
 
  template<class T, class Ref, class Ptr>
  struct __list_iterator // 定义迭代器
  {
    typedef list_node<T> Node;
    typedef __list_iterator<T, Ref, Ptr> iterator;
    // 在list类里面:
    // typedef __list_iterator<T, T&, T*>             iterator;
        // typedef __list_iterator<T, const T&, const T*> const_iterator;
    Node* _node;
 
    __list_iterator(Node* node)
      :_node(node)
    {}
 
    bool operator!=(const iterator& it)
    {
      return _node != it._node;
    }
    //T& operator*()
    Ref operator*()
    {
      return _node->_data;  // 返回结点的数据
    }
    //T* operator->()
    Ptr operator->()
    {
      return &(operator*());
      //即 return &(_node->_data);
    }
    iterator& operator++()
    {
      _node = _node->_next;
      return *this; // 返回加加后的值
    }
    iterator operator++(int)
    {
      iterator tmp(*this); // 拷贝构造一个tmp存储原来的值
      _node = _node->_next;
      return tmp; // 返回加加前的值
    }
    iterator& operator--()
    {
      _node = _node->_prev;
      return *this; // 返回减减后的值
    }
    iterator operator--(int)
    {
      iterator tmp(*this); // 拷贝构造一个tmp存储原来的值
      _node = _node->prev;
      return tmp; // 返回减减前的值
    }
  };
 
  template<class T>
  class list // 定义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()// begin是实际数据的第一个,_head 是哨兵位头结点
    {
      return iterator(_head->_next);
    }
    iterator end()// end是实际数据的下一个
    {
      return iterator(_head);
    }
 
    //reverse_iterator rbegin()//按照以前的理解,rbegin指向最后一个数据
    //{
    //  //return reverse_iterator(_head->_prev);
    //  return reverse_iterator(--end());
    //}
    //reverse_iterator rend()//按照以前的理解,rend指向第一个数据前一个(哨兵位)
    //{
    //  //return reverse_iterator(_head);
    //  return reverse_iterator(end());
    //}
 
    //const_reverse_iterator rbegin() const
    //{
    //  //return const_reverse_iterator(_head->_prev);
    //  return const_reverse_iterator(--end());
    //}
    //const_reverse_iterator rend() const
    //{
    //  //return const_reverse_iterator(_head);
    //  return const_reverse_iterator(end());
    //}
 
    reverse_iterator rbegin()// 对称实现
    {
      //return reverse_iterator(_head->_prev);
      //return reverse_iterator(--end());
      return reverse_iterator(end());
    }
    reverse_iterator rend()
    {
      //return reverse_iterator(_head);
      //return reverse_iterator(end());
      return reverse_iterator(begin());
    }
 
    const_reverse_iterator rbegin() const
    {
      //return const_reverse_iterator(_head->_prev);
      return const_reverse_iterator(end());
    }
    const_reverse_iterator rend() const
    {
      //return const_reverse_iterator(_head);
      return const_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)也行(类里面可以省略<T>,类外不行>
    {
      std::swap(_head, x._head); // 换哨兵位头结点就行
    }
 
    list(const list<T>& lt)//lt2(lt1)
    {
      empty_init();
      list<T> tmp(lt.begin(), lt.end()); // 迭代器区间构造一个(lt1)
      swap(tmp); // 直接和lt2换哨兵位头结点
    }
    list<T>& operator=(list<T> lt)//lt3 = lt1 这里lt1直接深拷贝给lt,lt是局部对象,出来作用域直接调析构
    {
      swap(lt);// 把深拷贝出来的lt和lt3交换
      return *this; // 把lt3返回
    }
 
    ~list()
    {
      clear();
      delete _head;
      _head = nullptr;
    }
    void clear()
    {
      iterator it = begin();
      while (it != end())
      {
        it = erase(it); // 返回删除位置的下一个结点
      }
    }
 
    iterator insert(iterator pos, const T& x)
    {
      Node* cur = pos._node;
      Node* prev = cur->_prev;
      Node* NewNode = new Node(x);
 
      prev->_next = NewNode;
      NewNode->_prev = prev;
      NewNode->_next = cur;
      cur->_prev = NewNode;
 
      return iterator(NewNode);
    }
    void push_back(const T& x)
    {
      //Node* tail = _head->_prev;
      //Node* NewNode = new Node(x);
       思路图:head        tail  NewNode
      //tail->_next = NewNode;
      //NewNode->_prev = tail;
      //_head->_prev = NewNode;
      //NewNode->_next = _head;
      insert(end(), x);
    }
    void push_front(const T& x)
    {
      insert(begin(), x);
    }
 
    iterator erase(iterator pos)
    {
      assert(pos != end());
      Node* cur = pos._node; // 删cur
      Node* prev = cur->_prev;
 
      prev->_next = cur->_next; // cur前一个指向cur后一个
      cur->_next->_prev = prev; // cur后一个指回cur前一个
 
      delete cur;
      return iterator(prev->_next); // 返回删除位置下一个
    }
    void pop_back()
    {
      erase(begin());
    }
    void pop_front()
    {
      erase(--end());
    }
 
  private:
    Node* _head; // 哨兵位头结点
  };
}

Test.cpp:(写到这忽然发现以前的Test.cpp都习惯写成Test.c 了,懂就刑)

#define _CRT_SECURE_NO_WARNINGS 1
 
#include "list.h"
 
namespace rtx
{
  void Test_reverse_iterator()
  {
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);
    lt.push_back(5);
 
    list<int>::iterator it = lt.begin();
    while (it != lt.end())
    {
      cout << *it << " ";
      ++it;
    }
    cout << endl;
 
    list<int>::reverse_iterator rit = lt.rbegin();
    while (rit != lt.rend())
    {
      cout << *rit << " ";
      ++rit;
    }
    cout << endl;
  }
}
 
int main()
{
  rtx::Test_reverse_iterator();
 
  return 0;
}

以后为了和库里面的类似,所以还是艺术地实现对称的反向迭代器好。

写到这可能还不知道我们实现的反向迭代器有多强(只要提供一个正向迭代器就行)

我们试试把 vector 的弄出来,在vector.h里 #include "reverse_iterator.h"

和上面一样只需在vector类里面加上下面的代码:

一模一样,你甚至可以一步复制粘贴,位置也不改了:

    typedef __reverse_iterator<iterator, T&, T*> reverse_iterator; // 传正向迭代器封装出反向迭代器
    typedef __reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;
 
    reverse_iterator rbegin()// 对称实现
    {
      //return reverse_iterator(_head->_prev);
      //return reverse_iterator(--end());
      return reverse_iterator(end());
    }
    reverse_iterator rend()
    {
      //return reverse_iterator(_head);
      //return reverse_iterator(end());
      return reverse_iterator(begin());
    }
 
    const_reverse_iterator rbegin() const
    {
      //return const_reverse_iterator(_head->_prev);
      return const_reverse_iterator(end());
    }
    const_reverse_iterator rend() const
    {
      //return const_reverse_iterator(_head);
      return const_reverse_iterator(begin());
    }

所以vector.h就是这样的:

vector.h

#pragma once
 
#include<iostream>
#include<assert.h>
#include<string>
#include "reverse_iterator.h"
using namespace std;
 
namespace rtx
{
  template<class T>
  class vector
  {
  public:
    typedef T* iterator;
    typedef const T* const_iterator;
 
    typedef __reverse_iterator<iterator, T&, T*> reverse_iterator; // 传正向迭代器封装出反向迭代器
    typedef __reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;
 
    reverse_iterator rbegin()// 对称实现
    {
      //return reverse_iterator(_head->_prev);
      //return reverse_iterator(--end());
      return reverse_iterator(end());
    }
    reverse_iterator rend()
    {
      //return reverse_iterator(_head);
      //return reverse_iterator(end());
      return reverse_iterator(begin());
    }
 
    const_reverse_iterator rbegin() const
    {
      //return const_reverse_iterator(_head->_prev);
      return const_reverse_iterator(end());
    }
    const_reverse_iterator rend() const
    {
      //return const_reverse_iterator(_head);
      return const_reverse_iterator(begin());
    }
 
    vector()
      :_start(nullptr)
      , _finish(nullptr)
      , _end_of_storage(nullptr)
    {}
    ~vector()
    {
      delete[] _start;
      _start = _finish = _end_of_storage = nullptr;
    }
 
    size_t size() const
    {
      return _finish - _start;
    }
    size_t capacity() const
    {
      return _end_of_storage - _start;
    }
 
    void push_back(const T& x)
    {
      //if (_finish == _end_of_storage)
      //{
      //  reserve(capacity() == 0 ? 4 : capacity() * 2);
      //}
      //*_finish = x;
      //++_finish;
      insert(end(), x);
    }
    void reserve(size_t n)
    {
      if (n > capacity())
      {
        size_t sz = size();
        T* tmp = new T[n];
        if (_start)
        {
          //memcpy(tmp, _start, sizeof(T) * sz); //浅拷贝,不行
 
          for (size_t i = 0; i < sz; i++)// 如果T是int,一个一个拷贝没问题
          {
            tmp[i] = _start[i];// 如果T是string等自定义问题,一个一个拷贝调用的是T的深拷贝,也不会出问题。
          }
          delete[] _start;
        }
        _start = tmp;
        _finish = tmp + sz;
        _end_of_storage = tmp + n;
      }
    }
 
    T& operator[](size_t pos)
    {
      assert(pos < size());
      return *(_start + pos);
    }
    const T& operator[](size_t pos) const
    {
      assert(pos < size());
      return *(_start + pos);
    }
 
    iterator begin()
    {
      return _start;
    }
    iterator end()
    {
      return _finish;
    }
    const_iterator begin() const
    {
      return _start;
    }
    const_iterator end() const
    {
      return _finish;
    }
 
    template<class InputInterator>
    vector(InputInterator first, InputInterator last)
      :_start(nullptr)
      , _finish(nullptr)
      , _end_of_storage(nullptr)
    {
      while (first != last)
      {
        push_back(*first);
        ++first;
      }
    }
 
    void resize(size_t n, const T& val = T())
    {
      if (n > capacity())
      {
        reserve(n);
      }
      if (n > size())
      {
        while (_finish != _start + n)
        {
          *_finish = val;
          ++_finish;
        }
      }
      else
      {
        _finish = _start + n;
      }
    }
 
    void pop_back()
    {
      assert(_finish > _start);
      --_finish;
    }
 
    iterator insert(iterator pos, const T& val)
    {
      assert(pos >= _start);// ①检查pos是否越界
      assert(pos <= _finish);
 
      if (_finish == _end_of_storage)// ②检查是否需要扩容
      {
        size_t len = pos - _start;// 记录一下pos到_start的距离
        reserve(capacity() == 0 ? 4 : capacity() * 2);
        pos = _start + len;// 迭代器失效问题,扩容后pos还是指向原来的空间,更新一下pos,
        //而且形参不会影响实参,传引用的话begin等就传不了,所以用返回解决
      }
 
      iterator right = _finish - 1;// ③移动数据
      while (right >= pos)
      {
        *(right + 1) = *right;
        --right;
      }
 
      *pos = val;// ④插入数据
      ++_finish;
      return pos;
    }
 
    iterator erase(iterator pos)
    {
      assert(pos >= _start);
      assert(pos < _finish);// 不能<= 因为_finish指向的是最后一个数据的下一个
 
      iterator left = pos + 1;
      while (left < _finish)
      {
        *(left - 1) = *left;
        ++left;
      }
      --_finish;
      return pos;//此时pos就是删除位置下一个位置迭代器
    }
 
    //vector(const vector<T>& v)// 传统写法
    //{
    //  reserve(v.capacity());
    //  // memcpy(_start, v._start, v.size() * sizeof(T));  // 会翻车
    //  for (const auto& e : v)
    //  {
    //    push_back(e);
    //  }
    //}
    void swap(vector<T>& v)
    {
      std::swap(_start, v._start);
      std::swap(_finish, v._finish);
      std::swap(_end_of_storage, v._end_of_storage);
    }
 
    vector(const vector<T>& v)// 现代写法
      :_start(nullptr)
      , _finish(nullptr)
      , _end_of_storage(nullptr)
    {
      vector<T> tmp(v.begin(), v.end());
      swap(tmp);
    }
 
    vector<T>& operator=(vector<T> v)// 现代写法
    {
      swap(v);
      return *this;
    }
 
  private:
    iterator _start;
    iterator _finish;
    iterator _end_of_storage;
  };
}

Test.cpp

#define _CRT_SECURE_NO_WARNINGS 1
 
#include "list.h"
#include "vector.h"
 
namespace rtx
{
  void Test_reverse_iterator()
  {
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);
    lt.push_back(5);
 
    list<int>::iterator it = lt.begin();
    while (it != lt.end())
    {
      cout << *it << " ";
      ++it;
    }
    cout << endl;
 
    list<int>::reverse_iterator rit = lt.rbegin();
    while (rit != lt.rend())
    {
      cout << *rit << " ";
      ++rit;
    }
    cout << endl;
  }
 
  void Test_reverse_iterator2()
  {
    vector<int> lt;//为了方便lt的名字都不改成常用的v了
    lt.push_back(10);
    lt.push_back(20);
    lt.push_back(30);
    lt.push_back(40);
    lt.push_back(50);
 
    vector<int>::iterator it = lt.begin();
    while (it != lt.end())
    {
      cout << *it << " ";
      ++it;
    }
    cout << endl;
 
    vector<int>::reverse_iterator rit = lt.rbegin();
    while (rit != lt.rend())
    {
      cout << *rit << " ";
      ++rit;
    }
    cout << endl;
  }
}
 
int main()
{
  //rtx::Test_reverse_iterator();
  rtx::Test_reverse_iterator2();
 
  return 0;
}

刑,反向迭代器就讲到这里了,讲了这么多属实有点麻烦,但了解原理后就很方便了。

所有正向迭代器++和--的容器都能用这个反向迭代器了。


3.  迭代器的功能分类

迭代器从功能可以分为这三类:单向迭代器,双向迭代器,随机迭代器,(文档有说明)

其中只有单向迭代器不支持上面实现的反向迭代器,

对应的是没讲的,forward_list单链表和蓝线的下面两个哈希表


下面的迭代器可以看作是上面的迭代器的特殊形式,所以算法库里的传参就有这样的命名:


本篇完。

到这里我们已经讲了容器适配器和迭代器适配器,体会了适配器封装和复用的特点。

软件开发提倡的就是能复用就复用,尽量不要自己写。

到这里我们基本已经把C++(简单的学了),后面继续融合地讲,先讲讲模板没讲的东西。

再讲C++的三大特性里的继承和多态。还有数据结构关于树的内容,map和set容器。

目录
相关文章
|
17天前
|
存储 算法 C++
【c++丨STL】priority_queue(优先级队列)的使用与模拟实现
本文介绍了STL中的容器适配器`priority_queue`(优先级队列)。`priority_queue`根据严格的弱排序标准设计,确保其第一个元素始终是最大元素。它底层使用堆结构实现,支持大堆和小堆,默认为大堆。常用操作包括构造函数、`empty`、`size`、`top`、`push`、`pop`和`swap`等。我们还模拟实现了`priority_queue`,通过仿函数控制堆的类型,并调用封装容器的接口实现功能。最后,感谢大家的支持与关注。
54 1
|
6月前
|
C++
C++(十七)仿函数
### Functor 仿函数简介 Functor(仿函数)是一种通过在类中实现 `operator()` 使其行为像函数的对象。这种方式可以让类拥有更多可定制的功能,同时保持函数般的简洁调用方式。下面展示了如何定义和使用一个计算幂运算的仿函数类,并通过示例说明了其在 `std::sort` 中的优势与灵活性。
|
7月前
|
C++ 容器
【C/C++笔记】迭代器
【C/C++笔记】迭代器
67 1
|
7月前
|
存储 安全 程序员
【C/C++笔记】迭代器范围
【C/C++笔记】迭代器范围
92 0
|
8月前
|
存储 算法 Java
【C++】优先级队列priority_queue模拟实现&&仿函数
【C++】优先级队列priority_queue模拟实现&&仿函数
60 1
|
8月前
|
C++ 容器
【C++】string类的使用①(迭代器接口begin,end,rbegin和rend)
迭代器接口是获取容器元素指针的成员函数。`begin()`返回首元素的正向迭代器,`end()`返回末元素之后的位置。`rbegin()`和`rend()`提供反向迭代器,分别指向尾元素和首元素之前。C++11增加了const版本以供只读访问。示例代码展示了如何使用这些迭代器遍历字符串。
|
8月前
|
存储 算法 C语言
【C++】详解STL的适配器容器之一:优先级队列 priority_queue
【C++】详解STL的适配器容器之一:优先级队列 priority_queue
|
25天前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
4天前
|
设计模式 安全 C++
【C++进阶】特殊类设计 && 单例模式
通过对特殊类设计和单例模式的深入探讨,我们可以更好地设计和实现复杂的C++程序。特殊类设计提高了代码的安全性和可维护性,而单例模式则确保类的唯一实例性和全局访问性。理解并掌握这些高级设计技巧,对于提升C++编程水平至关重要。
34 16
|
8天前
|
安全 C++
【c++】继承(继承的定义格式、赋值兼容转换、多继承、派生类默认成员函数规则、继承与友元、继承与静态成员)
本文深入探讨了C++中的继承机制,作为面向对象编程(OOP)的核心特性之一。继承通过允许派生类扩展基类的属性和方法,极大促进了代码复用,增强了代码的可维护性和可扩展性。文章详细介绍了继承的基本概念、定义格式、继承方式(public、protected、private)、赋值兼容转换、作用域问题、默认成员函数规则、继承与友元、静态成员、多继承及菱形继承问题,并对比了继承与组合的优缺点。最后总结指出,虽然继承提高了代码灵活性和复用率,但也带来了耦合度高的问题,建议在“has-a”和“is-a”关系同时存在时优先使用组合。
51 6