10.1 C++ STL 模板适配与迭代器

这篇具有很好参考价值的文章主要介绍了10.1 C++ STL 模板适配与迭代器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

STL(Standard Template Library)标准模板库提供了模板适配器和迭代器等重要概念,为开发者提供了高效、灵活和方便的编程工具。模板适配器是指一组模板类或函数,它们提供一种适配机制,使得现有的模板能够适应新的需求。而迭代器则是STL中的令一种重要的概念,它是一个抽象化的数据访问机制,通过迭代器可以遍历STL容器中的元素。适配器与迭代器两者的紧密配合,使得开发者能够高效地处理容器中的元素,提高了代码的复用性和可维护性。

10.1 函数对象适配器

Bind2nd 是一个函数适配器,可以用来将一个双参函数转换成一个单参函数。使用该适配器可以修改函数中的第二个参数,而将第一个参数保持不变。

bind2nd 适配器的具体用法如下:

template <class Operation>
typename binder2nd<Operation>::type
bind2nd(const Operation& op, const typename Operation::second_argument_type& arg);

其中,Operation是一个二元操作函数对象类型(例如,std::less),而arg是该函数中的第二个参数。

bind2nd 会返回一个binder2nd类型的函数对象,它是一个可调用的单参函数对象,可以代替原始的双参函数对象,并将该函数对象的第二个参数固定为arg,从而实现单参数函数的调用。

如下所示,这段代码实现了绑定参数实现对函数对象的适配,使之可以传递参数,其定义了一个名为MyPrint的类,它继承自二元函数对象类binary_function,并重载了operator()操作符。通过模板参数,指定第一个参数类型为int,第二个参数类型也为int,返回值类型为void。在operator()中,对两个int类型的参数valstart进行加法运算,并输出结果到控制台。

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

// binary_function (val= > 参数类型1 start=> 参数类型2 void=> 返回值类型)
class MyPrint :public binary_function<int,int,void>
{
public:void operator()(int val, int start) const {
    cout << val + start << endl;
  }
};

int main(int argc, char* argv[])
{
  vector<int> var = {1,2,3,4,5,6,7,8,9,10};

  int num;
  cin >> num;

  // 让MyPrint函数绑定num参数,传参是传递到MyPrint中
  for_each(var.begin(), var.end(), bind2nd(MyPrint(),num));
  system("pause");
  return 0;
}

10.2 函数指针适配器

Ptr_fun 是一个函数适配器,可以将普通函数转换为函数对象(Functor),从而使得可以以函数对象的方式调用该函数。它通常用于STL提供的算法函数(如 sort、find等),这些算法函数要求传入的参数为函数对象,而普通函数并不满足这个要求。

使用ptr_fun的一般步骤为:

  • 在定义函数时,将函数声明为普通函数类型。
  • 在使用ptr_fun适配器时,通过参数列表将想要转换的函数名作为参数传入ptr_fun中。
  • 将得到的适配后的函数对象作为参数传递给调用该函数的算法函数。

下面是一个简单的例子,当函数无法直接绑定参数是,可以将函数指针适配为函数对象,然后再向内部传递参数:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

void MyPrint(int val,int start)
{
  cout << val + start << " ";
}

int main(int argc, char* argv[])
{
  vector<int> var = {1,2,3,4,5,6,7,8,9,10};

  for_each(var.begin(), var.end(),bind2nd(ptr_fun(MyPrint),100) );
  system("pause");
  return 0;
}

10.3 容器取反适配器

Not1 是一个函数适配器,用于生成一个新函数对象,将原函数对象的逻辑取反。在使用not1这个适配器时,需要注意函数对象必须是一个一元谓词,也就是说,只接受一个参数并返回布尔值的函数对象。适配后的新函数对象接受一个参数,它的返回值取决于原函数对象的返回值,并将其取反。

以下是 not1 适配器的定义:

template <typename Predicate>
std::unary_negate<Predicate> not1(const Predicate& pred);

其中Predicate是一个一元谓词,而返回值是一个封装了谓词的std::unary_negate对象,它是一个可调用的函数对象,并可以在STL的算法函数中使用。

下面是一个使用not1的例子,我们想要找到第一个大于5的数是多少,但由于加上了not1取反,则输出的数据为小于5的数据。

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

class MyPrint : public unary_function<int,bool>
{
public:bool operator()(int val) const {
       return val > 5; // 找大于5的数
  }
};

int main(int argc, char* argv[])
{
  vector<int> var = {1,2,3,4,5,6,7,8,9,10};

  // 寻找第一个大于5的数,并遍历出来
  vector<int>::iterator pos = find_if(var.begin(), var.end(), not1(MyPrint()));
  if (pos != var.end())
    cout << *pos << endl;

  system("pause");
  return 0;
}

10.4 文件流对象拷贝文件

Istream_iterator 和 Ostream_iterator 是STL提供的两种迭代器适配器,它们分别用于将输入流和输出流封装成迭代器的形式,以便于使用STL提供的算法函数处理输入和输出流。

  • istream_iterator 可以通过重载 *、++== 等操作符,从输入流中读取数据,并形成一个可遍历的数据集合。
  • ostream_iterator 可以被用于将某个容器的元素写入输出流,它们提供了一个高效的方式,通过大量数据时不需要定义临时的缓冲区,而是直接将元素写入到流里,这使得它成为了输出大量数据时的好选择。

如下一段代码展示了通过绑定istream输入流对象,实现向前迭代动态拷贝文件到指定目录下的功能实现。

#include <iostream>
#include <iterator>
#include <fstream>
#include <string>
#include <algorithm>

using namespace std;

void Copy_Log(string src_path, string dst_path)
{
  ifstream read_file;
  ofstream write_file;

  read_file.open(src_path, ios::in);
  read_file >> noskipws;
  write_file.open(dst_path, ios::out);

  istream_iterator<char> iter_iFile(read_file);
  ostream_iterator<char> iter_oFile(write_file);

  copy(iter_iFile, istream_iterator<char>(), iter_oFile);
}

int main(int argc, char* argv[])
{
  Copy_Log("c:\\lyshark.txt", "c:\\new.txt");
  system("pause");
  return 0;
}

10.5 向前/后插入迭代器

Front_insert_iterator 和 Back_insert_iterator 是两种STL提供的迭代器适配器,主要用于实现容器的插入操作。

back_inserter适配器可以将元素插入到容器的尾部,而front_inserter则是将元素插入到容器的头部。这两种适配器都是在使用中间层的帮助下实现容器的插入操作,其主要作用是在输出迭代器(通常是一个容器)的末尾自动添加新的元素。

  • back_insert_iterator:将元素追加到容器的末尾,实现方式是通过调用容器的push_back函数实现。
  • front_insert_iterator:将元素插入到容器的头部,实现方式是通过调用容器的push_front函数实现。

下面是具体用例,通过使用插入迭代器我们可以将一组数据插入到容器中的前或后等位置。

#include <iostream>
#include <iterator>
#include <set>
#include <deque>
#include <vector>
#include <algorithm>

using namespace std;

int main(int argc, char* argv[])
{
  // 插入迭代器: 将两个数组合并,并插入到集合容器st中
  int iArray1[] = { 1, 3, 5, 7, 9 };
  int iArray2[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
  set<int> st;

  merge(iArray1, iArray1 + 5, iArray2, iArray2 + 8, insert_iterator<set<int>>(st,st.begin()));
  copy(st.begin(), st.end(), ostream_iterator<int>(cout, " "));    // 输出 st 内部的元素结果
  cout << endl;

  // 向前插入迭代器
  deque<int> deq = {1,2,3};
  front_insert_iterator<deque<int>> fii(deq);  // 向前插入
  *fii++ = 0;
  *fii++ = -1;
  copy(deq.begin(), deq.end(), ostream_iterator<int>(cout, " "));  // 输出 deq 内部的元素结果
  cout << endl;

  // 向后插入迭代器
  int iArray3[] = { 1, 2, 3, 4 };
  int len = sizeof(iArray3) / sizeof(int);
  vector<int> ve = {5,6};

  // 将数组元素从后插入到ve容器中
  copy(iArray3,iArray3+len,back_insert_iterator<vector<int>>(ve));
  copy(ve.begin(), ve.end(), ostream_iterator<int>(cout, " "));    // 输出 deq 内部的元素结果

  system("pause");
  return 0;
}

10.6 容器反向迭代器

Reverse_iterator 是STL提供的一种用于反向迭代器的适配器。它能够处理正向容器,并将其转换为反向容器,这使得可以使用STL通用算法从容器的末尾向前遍历。

一个reverse_iterator对象接受一个普通迭代器参数,并将该迭代器反转。如此一来,通过++运算符将使迭代器指向前一个元素,而*运算符返回的是它所指向的下一个元素。

下面是reverse_iterator的定义:

template<class Iterator>
class reverse_iterator {
public:
    typedef std::reverse_iterator<Iterator>    reverse_iterator; // C++11

    typedef Iterator                           iterator_type;
    typedef typename Iterator::iterator_category iterator_category;
    typedef typename Iterator::value_type      value_type;
    typedef typename Iterator::difference_type difference_type;
    typedef typename Iterator::pointer         pointer;
    typedef typename Iterator::reference       reference;

    // 构造函数
    reverse_iterator();
    explicit reverse_iterator(typename iterator_type::pointer p);
    explicit reverse_iterator(const iterator_type& x);
    template<class U>
      reverse_iterator (const reverse_iterator<U>& rev_it); // C++11

    // 迭代器操作
    reverse_iterator& operator++();
    reverse_iterator operator++(int);
    reverse_iterator& operator--();
    reverse_iterator operator--(int);
    reverse_iterator operator+ (difference_type n) const;
    reverse_iterator& operator+= (difference_type n);
    reverse_iterator operator- (difference_type n) const;
    reverse_iterator& operator-= (difference_type n);
    reference operator[](difference_type n) const;
    pointer operator->() const;
    reference operator*() const;
    iterator_type base() const;

    // 友元函数
    template<class U>
      friend class reverse_iterator;
    template<class U>
      bool operator== (const reverse_iterator<U>& rhs) const;
    template<class U>
      bool operator!= (const reverse_iterator<U>& rhs) const;
};

下面是一个使用reverse_iterator的例子,该迭代器是一个用随机访问迭代器构造出来的迭代器,用于反向迭代容器元素。文章来源地址https://www.toymoban.com/news/detail-655741.html

#include <iostream>
#include <iterator>
#include <vector>
#include <list>
#include <algorithm>

using namespace std;

int main(int argc, char* argv[])
{
  vector<int> var;
  back_insert_iterator< vector<int>> bii(var);
  *bii++ = 3;
  *bii++ = 9;
  *bii++ = 10;

  // 反向迭代器定义
  reverse_iterator<vector<int>::iterator> rfirst(var.end());
  reverse_iterator<vector<int>::iterator> rend(var.begin());

  // 从尾到头打印
  copy(rfirst, rend, ostream_iterator<int>(cout, " "));

  system("pause");
  return 0;
}

到了这里,关于10.1 C++ STL 模板适配与迭代器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构与算法】C++的STL模板(迭代器iterator、容器vector、队列queue、集合set、映射map)以及算法例题

    更多算法例题链接: 【数据结构与算法】递推法和递归法解题(递归递推算法典型例题) 什么是迭代器(iterator) 迭代器(iterator)的定义: 迭代器是一种检查容器内元素并遍历元素的数据类型。 迭代器提供对一个容器中的对象的访问方法,并且定义了容器中对象的范围。 容器

    2024年04月14日
    浏览(37)
  • 面试之快速学习STL-迭代适配器

    参考:http://c.biancheng.net/view/7255.html 例子: 想使用反向迭代器实现逆序遍历容器,则该容器的迭代器类型必须是双向迭代器或者随机访问迭代器。 常见操作 注意这里不能用std::list,因为它是双向迭代器, +3的操作需要随机访问迭代器 。故联想到std::list排序只能使用list提供的

    2024年02月11日
    浏览(30)
  • 标准模板库STL——迭代器

    目录 四类迭代器概述 代码段 普通正向迭代器 普通反向迭代器 常量正向迭代器 常量反向迭代器 四类迭代器 普通正向迭代器 iterator 常量正向迭代器 const_iterator 普通反向迭代器 reverse_iterator 常量反向迭代器 const_reverse_iterator 解释说明 普通表示可以读元素,也可以写元素; 常量

    2024年02月12日
    浏览(24)
  • 23 标准模板库STL之迭代器

    概述         迭代器作为STL中的三大组件之一,是容器和算法的粘合剂。迭代器提供了访问容器中元素的方法,每一种容器都提供了自己的迭代器,而这些迭代器向外界隐藏了容器的内部结构。算法使用迭代器访问容器中的元素,不需要关心容器的内部结构。        

    2024年02月05日
    浏览(24)
  • STL标准模板库 vector容器与迭代器入门

    vector 就是一个连续的数据 C++11 std::vector a ={1,4,2,6,7}; 可以使用花括号来定义 容器的功能就是存储数据 迭代器的功能就是指向数据,并且可以实现前后移动(指针)算法和容器的接口的存在 vector功能是长度可变的数组, 身在栈上 里面的数据存储在堆上 因为栈不可动态扩容

    2023年04月23日
    浏览(34)
  • OpenCL编程指南-10.1C++包装器API

    C++API划分为多个类,分别映射到一个OpenCL C类型,例如,cl::Memory类就映射到OpenCL C中的cl_mem。不过,C++ API会尽可能使用继承提供额外的一层类型抽象;例如,类cl::Buffer派生自基类cl::Memory,表示所有可能的OpenCL内存对象的1维内存子类。类层次体系结构见图12-1。 一般地,C++类

    2024年02月09日
    浏览(26)
  • 22 标准模板库STL之容器适配器

    概述         提到适配器,我们的第一印象是想到设计模式中的适配器模式:将一个类的接口转化为另一个类的接口,使原本不兼容而不能合作的两个类,可以一起工作。STL中的容器适配器与此类似,是一个封装了序列容器的类模板,它在一般序列容器的基础上提供了一

    2024年02月05日
    浏览(30)
  • C++迭代器(STL迭代器)iterator详解

    要访问顺序容器和关联容器中的元素,需要通过“迭代器(iterator)”进行。迭代器是一个变量,相当于容器和操纵容器的算法之间的中介。迭代器可以指向容器中的某个元素,通过迭代器就可以读写它指向的元素。从这一点上看,迭代器和指针类似。 迭代器按照定义方式分

    2024年02月03日
    浏览(34)
  • 【c++手撕STL】之迭代器

    在C++ STL (Standard Template Library,标准模板库)中,迭代器是一个非常重要的组成部分。迭代器像是一个指针,负责在容器的元素之间移动,并且能够访问到容器的元素。 C++ STL 提供了几种类型的迭代器,每种迭代器都有它独特的功能和特性: 输入迭代器(Input Iterators) :只读不

    2024年02月12日
    浏览(30)
  • C++ [STL容器反向迭代器]

    本文已收录至《C++语言》专栏! 作者:ARMCSKGT 我们知道STL大部分容器都有迭代器,迭代器又分为正向迭代器和反向迭代器,对于正向迭代器以及实现前面我们已经了解了不少,而反向迭代器的设计思想是 适配器模式 ,本节我们介绍反向迭代器的实现! 适配器是把一个类的接

    2024年02月11日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包