千家信息网

C++的STL迭代器怎么自定义

发表于:2024-11-30 作者:千家信息网编辑
千家信息网最后更新 2024年11月30日,这篇文章主要介绍"C++的STL迭代器怎么自定义"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"C++的STL迭代器怎么自定义"文章能帮助大家解决问题。C++
千家信息网最后更新 2024年11月30日C++的STL迭代器怎么自定义

这篇文章主要介绍"C++的STL迭代器怎么自定义"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"C++的STL迭代器怎么自定义"文章能帮助大家解决问题。

C++ STL 迭代器

了解如何使用 C++ 标准模板库 (STL) 的容器的关键之一是了解迭代器的工作原理。lists 和maps等容器的行为不像数组,因此您不能使用for循环来遍历其中的元素。同样,因为这些容器不能随机访问,所以不能使用简单的整数索引。你可以使用迭代器来引用容器的元素。

STL 容器和算法可以很好地协同工作的原因是它们彼此一无所知 - Alex Stepanov

迭代器是类似指针的对象,它允许程序在不暴露底层表示的情况下顺序地遍历容器的元素。迭代器可以通过递增和递减它们从一个元素前进到下一个元素。每个容器类型都有一个与之关联的不同迭代器。例如,迭代器 forlist声明为:

 std::list::iterator

迭代器类别

迭代器分为几类,因为不同的算法需要使用不同的迭代器。例如,该std::copy()算法需要一个可以通过递增来推进的迭代器,而该 std::reverse()算法需要一个可以递减的迭代器。在 C++ 语言中,该标准定义了五个不同的类别。

  • 输入迭代器

    • 只读且只能读取一次。

    • 例子: std::istream_iterator(istream& is)

  • 输出迭代器

    • 只写

    • 例如:std::ostream_iterator out_it (std::cout,", ");

  • 前向迭代器

    • 收集输入+输出迭代器

    • 示例:std::forward_list::iterator,std::unordered_map::iterator

  • 双向迭代器

    • 像前向迭代器,但也有 operator-

    • 例子: std::list::iterator

  • 随机访问迭代器

    • 已重载operator[],指针运算

    • 例子:std::vector::iterator

你可以在此处获得有关这些的更多信息

迭代器特征

迭代器特征允许算法以统一的方式访问有关特定迭代器的信息,以避免在需要遍历不同样式的容器时为每个特定情况重新实现所有迭代器。例如,查找元素std::listO(n)复杂性,而std::vector随机访问元素是O(1)复杂性(给定索引位置)。算法最好知道可以使用+=运算符(随机访问)或仅使用++运算符(转发)遍历容器,以选择更好的选择以降低计算的算法的复杂度。

迭代器特征如下:

  • difference_type

    • 表示迭代器距离的类型

    • 迭代器的类型差异p2 - p1

  • value_type

    • 迭代器指向的值的类型

  • pointer

    • 迭代器指向的指针值

    • 通常 value_type*

  • reference

    • 迭代器指向的引用值

    • 通常 value_type&

  • iterator category

    struct input_iterator_tag {};struct output_iterator_tag {};struct forward_iterator_tag : input_iterator_tag {};struct bidirectional_iterator_tag : forward_iterator_tag {};struct random_access_iterator_tag : bidirectional_iterator_tag {};
    • 标识由迭代器建模的迭代器概念。

    • 以下之一:

的定义iterator_traits看起来像:

// The basic version works for iterators with the member typetemplate struct iterator_traits{typedef typename Iterator::value_type value_type;typedef typename Iterator::difference_type difference_type;typedef typename Iterator::pointer pointer;typedef typename Iterator::reference reference;typedef typename Iterator::iterator_category iterator_category;};// A partial specialization takes care of pointer typestemplate struct iterator_traits{typedef T value_type;typedef ptrdiff_t difference_type;typedef T *pointer;typedef T &reference;typedef random_access_iterator_tag iterator_category;};// pointers to const typetemplate struct iterator_traits{typedef T value_type;typedef ptrdiff_t difference_type;typedef const T *pointer;typedef const T &reference;typedef random_access_iterator_tag iterator_category;};

有时,泛型算法需要知道其迭代器参数的值类型,即迭代器指向的类型。例如,要交换两个迭代器指向的值,就需要一个临时变量。

template void swap (Iterator a, Iterator b) {  typename Iterator::value_type tmp = *a;  *a = *b;  *b = tmp;}

这些特征还通过利用iterator_category成员提供的有关基本迭代器类别的知识来提高算法的效率算法可以使用这个"标签"来选择迭代器能够处理的最有效的实现,而不会影响处理各种迭代器类型的灵活性。

在下面的例子中,我们的目标是有一个单一的advance算法,可以根据迭代器类别自动执行正确的版本。

template void advance(InputIterator &i, Distance n, input_iterator_tag){for (; n > 0; --n)++i;}template void advance(BidirectionalIterator &i, Distance n   bidirectional_iterator_tag){if (n <= 0)for (; n > 0; --n)++i;elsefor (; n < 0; ++n)--i;}template void advance(RandomAccessIterator &i, Distance n, random_access_iterator_tag){i += n;}// Generic advance algorithm using compile-time dispatching based on function overloadingtemplate void advance(InputIterator i, Distance n){advance(i, n, typename iterator_traits::iterator_category());}

编写自定义迭代器

迭代器特征将自动适用于定义适当成员类型的任何迭代器类。自定义迭代器应该支持以下指针:

  • 如何检索该点的值

  • 如何增加/减少迭代点

  • 如何与其他迭代点进行比较

#include #include #include #include #include #include template  class MyArray {private:  ArrType *m_data;  unsigned int m_size;public:  class Iterator {  public:// iterator_trait associated typestypedef Iterator itr_type;typedef ArrType value_type;typedef ArrType &reference;typedef ArrType *pointer;typedef std::bidirectional_iterator_tag iterator_category;typedef std::ptrdiff_t difference_type;Iterator(pointer ptr) : m_itr_ptr(ptr) {}itr_type operator++() {  itr_type old_itr = *this;  m_itr_ptr++;  return old_itr;}itr_type operator++(int dummy) {  m_itr_ptr++;  return *this;}itr_type operator--() {  itr_type old_itr = *this;  m_itr_ptr--;  return old_itr;}itr_type operator--(int dummy) {  m_itr_ptr--;  return *this;}reference operator*() const { return *m_itr_ptr; }pointer operator->() const { return m_itr_ptr; }bool operator==(const itr_type &rhs) { return m_itr_ptr == rhs.m_itr_ptr; }bool operator!=(const itr_type &rhs) { return m_itr_ptr != rhs.m_itr_ptr; }  private:pointer m_itr_ptr;  };  MyArray(unsigned int size) : m_size(size) { m_data = new ArrType[m_size]; }  unsigned int size() const { return m_size; }  ArrType &operator[](unsigned int idx) {if (idx >= m_size)  throw std::runtime_error("Index out of range");return m_data[idx];  }  Iterator begin() { return Iterator(m_data); }  Iterator end() { return Iterator(m_data + m_size); }};int main(){  MyArray arr(3);  arr[0] = 2.6;  arr[1] = 5.2;  arr[2] = 8.9;  std::cout << "MyArray Contents: ";  for (MyArray::Iterator it = arr.begin(); it != arr.end(); it++) {std::cout << *it << " ";  }  std::cout << std::endl;  std::vector vec;  std::copy(arr.begin(), arr.end(), std::back_inserter(vec));  std::cout << "Vector Contents after copy: ";  for (std::vector::iterator it = vec.begin(); it != vec.end(); it++) {std::cout << *it << " ";  }  std::cout << std::endl;  std::cout << typeid(std::iterator_traits<  MyArray::Iterator>::iterator_category())   .name()<< std::endl;  return 0;}/*OUTPUTMyArray Contents: 2.6 5.2 8.9 Vector Contents after copy: 2.6 5.2 8.9 FSt26bidirectional_iterator_tagvE*/

迭代器和循环范围

基于范围的 for 循环(或简称为 range-for)以及auto,是 C++11 标准中添加的最重要的特性之一。

范围for循环的语法模板如下所示:

for (range_declaration : range_expression) { // loop body }

在 C++11/C++14 中,上述格式产生类似于以下的代码:

{    auto&& range = range_expression ;   // beginExpr is range.begin() and endExpr is range.end()  for (auto b = beginExpr, e = endExpr; b != e; ++b) { range_declaration = *b; // loop body  } }

基于范围的 for 循环的典型用法:

// Iterate over STL containerstd::vector v{1, 2, 3, 4};for (const auto &i : v)std::cout << i << "\n";

range for 循环的工作方式是创建一个指向向量第一个元素的迭代器,然后依次访问向量的每个元素,直到迭代器到达向量的最后一个元素,然后循环终止。在cppinsight可以观察到这种现象。

关于"C++的STL迭代器怎么自定义"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注行业资讯频道,小编每天都会为大家更新不同的知识点。

迭代 算法 元素 容器 类型 循环 C++ 不同 指向 特征 例子 指针 知识 类别 范围 复杂 向量 标准 工作 有关 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 租用服务器和自己部署服务器区别 定时 从另外一个数据库 复制 零基础想学做软件开发 软件开发 面试测试 绵阳做软件开发一年收入 广电网络安全保卫应急预案 张家口大数据服务器散热量 上海定制软件开发品质保障 数据库查看所有商品种类名称 讲述互联网科技的电视剧 autox安途公司 服务器 服务器信息安全管理 浙江java软件开发工程师 怎样在本地搭建软件开发环境 各种网络安全防护知识 学生可以学习网络安全知识吗 重庆服务器报废选哪家虚拟主机 欧洲互联网科技公司 sql数据库控制台怎么创建表 福建实践网络安全考试 完美测试软件开发 数据库给时间转换英文月份 广州优橙网络技术怎么样 一个应用程序可以接入多种数据库 单机msde数据库 新致软件开发 数据库查看所有商品种类名称 问道1.6怎么连接数据库 默认数据库安全吗 建立一个图书管理系统数据库截图
0