Mr Dk.'s BlogMr Dk.'s Blog
  • 🦆 About Me
  • ⛏️ Technology Stack
  • 🔗 Links
  • 🗒️ About Blog
  • Algorithm
  • C++
  • Compiler
  • Cryptography
  • DevOps
  • Docker
  • Git
  • Java
  • Linux
  • MS Office
  • MySQL
  • Network
  • Operating System
  • Performance
  • PostgreSQL
  • Productivity
  • Solidity
  • Vue.js
  • Web
  • Wireless
  • 🐧 How Linux Works (notes)
  • 🐧 Linux Kernel Comments (notes)
  • 🐧 Linux Kernel Development (notes)
  • 🐤 μc/OS-II Source Code (notes)
  • ☕ Understanding the JVM (notes)
  • ⛸️ Redis Implementation (notes)
  • 🗜️ Understanding Nginx (notes)
  • ⚙️ Netty in Action (notes)
  • ☁️ Spring Microservices (notes)
  • ⚒️ The Annotated STL Sources (notes)
  • ☕ Java Development Kit 8
GitHub
  • 🦆 About Me
  • ⛏️ Technology Stack
  • 🔗 Links
  • 🗒️ About Blog
  • Algorithm
  • C++
  • Compiler
  • Cryptography
  • DevOps
  • Docker
  • Git
  • Java
  • Linux
  • MS Office
  • MySQL
  • Network
  • Operating System
  • Performance
  • PostgreSQL
  • Productivity
  • Solidity
  • Vue.js
  • Web
  • Wireless
  • 🐧 How Linux Works (notes)
  • 🐧 Linux Kernel Comments (notes)
  • 🐧 Linux Kernel Development (notes)
  • 🐤 μc/OS-II Source Code (notes)
  • ☕ Understanding the JVM (notes)
  • ⛸️ Redis Implementation (notes)
  • 🗜️ Understanding Nginx (notes)
  • ⚙️ Netty in Action (notes)
  • ☁️ Spring Microservices (notes)
  • ⚒️ The Annotated STL Sources (notes)
  • ☕ Java Development Kit 8
GitHub
  • ⚒️ The Annotated STL Sources
    • Chapter 1 - STL 概论与版本简介

      • Chapter 1 - STL 概论与版本简介
    • Chapter 2 - 空间分配器 allocator

      • Chapter 2.1 - SGI 空间分配器
      • Chapter 2.2 - SGI 特殊的空间分配器
      • Chapter 2.3 - 内存基本处理工具
    • Chapter 3 - 迭代器概念与 traits 编程方法

      • Chapter 3.1-3.5 - 迭代器设计思维
      • Chapter 3.6 - iterator 源代码完整重列
      • Chapter 3.7 - SGI STL 的私房菜:__type_traits
    • Chapter 4 - 序列式容器

      • Chapter 4.2 - vector
      • Chapter 4.3 - list
      • Chapter 4.4 - deque
      • Chapter 4.5 - stack
      • Chapter 4.6 - queue
      • Chapter 4.7 - heap
      • Chapter 4.8 - priority_queue
      • Chapter 4.9 - slist
    • Chapter 5 - 关联式容器

      • Chapter 5.2 - RB-Tree
      • Chapter 5.3 - set & multiset
      • Chapter 5.3 - map & multimap
      • Chapter 5.7 - hashtable
      • Chapter 5.8 - hash_set
      • Chapter 5.8 - hash_map
      • Chapter 5.10 - hash_multiset
      • Chapter 5.11 - hash_multimap
    • Chapter 6 - 算法

      • Chapter 6.1-6.3 - 数值算法
      • Chapter 6.4 - 基本算法
      • Chapter 6.5 - set 相关算法
      • Chapter 6.7.1 - 数据处理算法
      • Chapter 6.7.2 - lower_bound
      • Chapter 6.7.3 - upper_bound
      • Chapter 6.7.5 - permutation
      • Chapter 6.7.7 - random_shuffle
      • Chapter 6.7.8 - partial_sort / partial_sort_copy
      • Chapter 6.7.9 - sort
      • Chapter 6.7.12 - nth_element
    • Chapter 7 - 仿函数 functors

      • Chapter 7 - 仿函数 functors
    • Chapter 8 - 适配器

      • Chapter 8.1-8.2 - Container Adapters
      • Chapter 8.3 - Iterator Adapters
      • Chapter 8.4 - Function Adapters

Chapter 8.3 - Iterator Adapters

Created by : Mr Dk.

2021 / 04 / 07 22:48

Nanjing, Jiangsu, China


8.3.1 Insert Iterators

每个插入迭代器内部维护了一个容器。当用户对插入迭代器进行 赋值 操作时,就在插入迭代器内部转变为底层容器的插入操作。其它迭代器的功能都被关闭,前进 / 后退 / 取值 / 解引用等操作都是没有意义的。

后向插入迭代器。对迭代器的赋值操作将导致从容器的尾端插入元素。

template <class _Container>
class back_insert_iterator {
protected:
  _Container* container; // 指向底层容器
public:
  typedef _Container          container_type;
  typedef output_iterator_tag iterator_category; // 输出迭代器 (只写不读)
  typedef void                value_type;
  typedef void                difference_type;
  typedef void                pointer;
  typedef void                reference;

  explicit back_insert_iterator(_Container& __x) : container(&__x /* 指向底层容器 */) {}
  back_insert_iterator<_Container>&
  operator=(const typename _Container::value_type& __value) { // 重载赋值运算符
    container->push_back(__value); // 转而调用底层容器的 push_back() 函数
    return *this;
  }
  back_insert_iterator<_Container>& operator*() { return *this; } // 其它迭代器操作没用
  back_insert_iterator<_Container>& operator++() { return *this; }
  back_insert_iterator<_Container>& operator++(int) { return *this; }
};

template <class _Container>
inline back_insert_iterator<_Container> back_inserter(_Container& __x) {
  return back_insert_iterator<_Container>(__x); // 便于返回迭代器的函数
}

前向插入迭代器。对迭代器的赋值操作将导致从容器前端插入元素。

template <class _Container>
class front_insert_iterator {
protected:
  _Container* container;
public:
  typedef _Container          container_type;
  typedef output_iterator_tag iterator_category; // 输出迭代器 (只写)
  typedef void                value_type;
  typedef void                difference_type;
  typedef void                pointer;
  typedef void                reference;

  explicit front_insert_iterator(_Container& __x) : container(&__x /* 指向底层容器 */) {}
  front_insert_iterator<_Container>&
  operator=(const typename _Container::value_type& __value) { // 重载赋值运算符
    container->push_front(__value); // 转而调用底层容器的 push_front() 函数
    return *this;
  }
  front_insert_iterator<_Container>& operator*() { return *this; }
  front_insert_iterator<_Container>& operator++() { return *this; }
  front_insert_iterator<_Container>& operator++(int) { return *this; }
};

template <class _Container>
inline front_insert_iterator<_Container> front_inserter(_Container& __x) {
  return front_insert_iterator<_Container>(__x); // 便于返回迭代器的函数
}

跟随结点的插入函数。在迭代器指示的结点 (之前) 插入元素,插入成功后将返回的迭代器自增,指向原迭代器指示的元素。即插入位置永远随着构造对象时指定的那个迭代器。

template <class _Container>
class insert_iterator {
protected:
  _Container* container;
  typename _Container::iterator iter;
public:
  typedef _Container          container_type;
  typedef output_iterator_tag iterator_category; // 输出迭代器 (只写)
  typedef void                value_type;
  typedef void                difference_type;
  typedef void                pointer;
  typedef void                reference;

  insert_iterator(_Container& __x, typename _Container::iterator __i)
    : container(&__x /* 指向底层容器 */), iter(__i /* 指示插入位置的迭代器 */) {}
  insert_iterator<_Container>&
  operator=(const typename _Container::value_type& __value) {
    iter = container->insert(iter, __value); // 在迭代器指示的位置插入
    ++iter;                                  // 重新指向构造函数指定的迭代器
    return *this;
  }
  insert_iterator<_Container>& operator*() { return *this; }
  insert_iterator<_Container>& operator++() { return *this; }
  insert_iterator<_Container>& operator++(int) { return *this; }
};

template <class _Container, class _Iterator>
inline
insert_iterator<_Container> inserter(_Container& __x, _Iterator __i)
{
  typedef typename _Container::iterator __iter;
  return insert_iterator<_Container>(__x, __iter(__i));
}

8.3.2 Reverse Iterators

反向迭代器将迭代器的移动行为翻转,改为从尾到头处理容器中的元素。反向迭代器内部维护了一个正向迭代器,只不过颠覆了正向迭代器的视角。

由于正向迭代器有 左闭右开 的特性,因此不能将反向迭代器简单实现为 begin 和 end 的互换。核心:先对类内的正向迭代器进行自减,然后再对该迭代器进行使用。这样 rbegin() 将会对应 end() 的前一个元素。说白了,左闭右开的视角不会变。

以下是 Random Access Iterators 对应的反向迭代器。由于支持随机存取,因此可以使用 +=、-= 等运算符。对于 Bidirectional Iterators 的反向迭代器,只对外提供重载后的 ++、-- 运算符。

class reverse_iterator {
  typedef reverse_iterator<_RandomAccessIterator, _Tp, _Reference, _Distance>
        _Self;
protected:
  _RandomAccessIterator current; // 维护正向迭代器,只需要颠覆其视角即可
public:
  typedef random_access_iterator_tag iterator_category; // 随机存取迭代器
  typedef _Tp                        value_type;
  typedef _Distance                  difference_type;
  typedef _Tp*                       pointer;
  typedef _Reference                 reference;

  reverse_iterator() {}
  explicit reverse_iterator(_RandomAccessIterator __x) : current(__x) {} // 可用一个已有的迭代器构造
  _RandomAccessIterator base() const { return current; }
  _Reference operator*() const { return *(current - 1); } // 访问当前迭代器所指的前一个元素
  pointer operator->() const { return &(operator*()); }   // 借用 * 运算符
  _Self& operator++() {
    --current; // 反向迭代器的 ++ 对应正向迭代器的 --
    return *this;
  }
  _Self operator++(int) {
    _Self __tmp = *this;
    --current;
    return __tmp;
  }
  _Self& operator--() {
    ++current; // 反向迭代器的 -- 对应正向迭代器的 ++
    return *this;
  }
  _Self operator--(int) {
    _Self __tmp = *this;
    ++current;
    return __tmp;
  }
  _Self operator+(_Distance __n) const {
    return _Self(current - __n); // 反向迭代器的 + 对应正向迭代器的 -
  }
  _Self& operator+=(_Distance __n) {
    current -= __n; // 反向迭代器的 += 对应正向迭代器的 -=
    return *this;
  }
  _Self operator-(_Distance __n) const {
    return _Self(current + __n); // 反向迭代器的 - 对应正向迭代器的 +
  }
  _Self& operator-=(_Distance __n) {
    current += __n; // 反向迭代器的 -= 对应正向迭代器的 +=
    return *this;
  }

  // 这里的第一个 * 使用的是当前类重载的 operator*,实际上访问的是 *(current - 1)
  // 第二个 * 特指 *this 为当前对象 (迭代器)
  // 这里的 + 也是使用当前类重载的 operator+,实际上表示 (current - __n)
  _Reference operator[](_Distance __n) const { return *(*this + __n); }
  // 实际上访问的是 *(current - __n - 1)
};

8.3.3 Stream Iterators

迭代器可以被绑定到一个 stream 上,使其拥有输入或输出的能力。

对于输入流迭代器来说,实际上就是在类内维护一个输入流 (istream)。对迭代器的 ++ 操作将会转而调用 istream 的 >> 操作获取输入。输入流是一个 Input Iterator,因为它是只读的。

template <class _Tp, class _Dist = ptrdiff_t> class istream_iterator;

template <class _Tp, class _Dist>
class istream_iterator {
  friend bool __STD_QUALIFIER
  operator== __STL_NULL_TMPL_ARGS (const istream_iterator&,
                                   const istream_iterator&);
protected:
  istream* _M_stream;   // 指向绑定的输入流
  _Tp _M_value;         // 暂存对读入的对象
  bool _M_end_marker;   // 流是否已结束
  void _M_read() {
    _M_end_marker = (*_M_stream) ? true : false;
    if (_M_end_marker) *_M_stream >> _M_value;   // 如果流未结束,则读取输入
    _M_end_marker = (*_M_stream) ? true : false;
  }
public:
  typedef input_iterator_tag  iterator_category; // 输入迭代器 (只读)
  typedef _Tp                 value_type;
  typedef _Dist               difference_type;
  typedef const _Tp*          pointer;
  typedef const _Tp&          reference;

  istream_iterator() : _M_stream(&cin), _M_end_marker(false) {}    // 默认输入流已结束 (通常用作 last 迭代器)
  istream_iterator(istream& __s) : _M_stream(&__s) { _M_read(); }  // 绑定输入流,并读入第一个元素
  reference operator*() const { return _M_value; }                 // 返回已读入并暂存的元素
  pointer operator->() const { return &(operator*()); }
  istream_iterator<_Tp, _Dist>& operator++() {
    _M_read();  // 调用一次读取函数
    return *this;
  }
  istream_iterator<_Tp, _Dist> operator++(int)  {
    istream_iterator<_Tp, _Dist> __tmp = *this;
    _M_read();  // 调用一次读取函数
    return __tmp;
  }
};

由于构造该迭代器时会调用一次 read() 造成阻塞,所以一定要在确定需要的时候才定义输入流迭代器。示例:

istream_iterator<int> first(cin);
istream_iterator<int> last;  // (cin, false)
copy(first, last, ..., ...); // while first != last

对于输出流迭代器来说,类内绑定了一个 ostream。用户对迭代器的 operator= 操作,将会转而调用 ostream 的 operator<< 输出操作。

template <class _Tp>
class ostream_iterator {
protected:
  ostream* _M_stream;     // 指向绑定的输出流
  const char* _M_string;  // 每输出一次后跟着输出的分隔字符串
public:
  typedef output_iterator_tag iterator_category;  // 输出迭代器 (只写)
  typedef void                value_type;
  typedef void                difference_type;
  typedef void                pointer;
  typedef void                reference;

  ostream_iterator(ostream& __s) : _M_stream(&__s), _M_string(0) {} // 默认没有分隔字符串
  ostream_iterator(ostream& __s, const char* __c)                   // 指定输出流和分隔字符串
    : _M_stream(&__s), _M_string(__c)  {}
  ostream_iterator<_Tp>& operator=(const _Tp& __value) {  // 重载赋值运算符
    *_M_stream << __value;                   // 输出赋值给迭代器的数值
    if (_M_string) *_M_stream << _M_string;  // 如果有分隔字符串的话,输出分隔字符串
    return *this;
  }
  ostream_iterator<_Tp>& operator*() { return *this; }     // 迭代器运算操作无效
  ostream_iterator<_Tp>& operator++() { return *this; }
  ostream_iterator<_Tp>& operator++(int) { return *this; }
};

一种可能的使用方式:

ostream_iterator<int> out(cout, " ");
copy(vec.begin(), vec.end(), out);
Edit this page on GitHub
Prev
Chapter 8.1-8.2 - Container Adapters
Next
Chapter 8.4 - Function Adapters