STL源码剖析笔记——适配器(adapters)

系列文章目录

STL源码剖析笔记——迭代器
STL源码剖析笔记——vector
STL源码剖析笔记——list
STL源码剖析笔记——deque、stack,queue
STL源码剖析笔记——Binary Heap、priority_queue
STL源码剖析笔记——AVL-tree、RB-tree、set、map、mutiset、mutimap
STL源码剖析笔记——哈希表、unordered_set、unordered_map、unordered_mutiset、unordered_mutimap
STL源码剖析笔记——仿函数(函数对象)
STL源码剖析笔记——适配器(adapters)

文章目录

  • 系列文章目录
    • 1. 定义
    • 2. 容器适配器
    • 3. 迭代器适配器
    • 4. 仿函数适配器
      • (1)not1、not2
      • (2)bind1st、bind2nd
      • (3)compose1、compose2
      • (4)ptr_fun


1. 定义

  适配器(Adapter)是指一些特定的容器或迭代器,它们提供了不同于其底层实现的接口,以便与算法或其他容器进行协同工作,是通过将底层实现进行改造,以满足特定的需求。适配器跟底层实现的关系是包含而不是继承。 主要分为三种:容器适配器,迭代器适配器,仿函数适配器。

2. 容器适配器

  STL提供的两个容器queue和stack,其实都只不过是一种配接器。它们通过修饰底层的deque接口实现特殊的功能。从queue和stack的构造来看,两者内部都包含了一个queue,封住了所有的deque对外接口,只开放符合queue和stack原则的几个函数。queue和stack是容器,本质上也是作用于容器之上的一个适配器。

template <class T, class Sequence=deque<T> > 
class stack {
protected:Sequence c; //底层容器
};template <class T, class Sequence = deque<T> >
class queue {
protected:Sequence c; //底层容器
};

3. 迭代器适配器

  STL提供了许多应用于迭代器身上的配接器,包括insert Iterators, reverse iterators, iostream iteratorsors。他们本身就是迭代器,也是作用于迭代器上的一个适配器。通过修饰底层的迭代器接口实现特殊的功能,以reverse iterators为例:
reverse iterators的主要作用是实现反向迭代器遍历,rbegin()和rend()函数都是通过它来实现。
在这里插入图片描述
  对于一般的迭代器来说,begin()指向的是第一个元素,end()指向的是最后一个元素的后一个位置,是[ begin(), end() ),前闭后开。现在反向迭代器应该要保持这种设定,即rbegin()指向的是最后一个元素,rend()指向的是第一个元素的前一个位置。而且这种功能就要通过reverse iterators适配器来实现。
在这里插入图片描述
  可以看到reverse iterators中包含了一个正向的迭代器,对这个反向迭代器进行取值的操作,其实就是对内部的正向迭代器的前一位进行取值;包括其他的operator++,operator–,operator+,operator-,其实都是根据要求对内部包含的正向迭代器进行操作。

4. 仿函数适配器

  仿函数适配器functor adapters (亦称为function adapters)是所有配接器中数量最庞大的一个族群,其配接灵活度也是前二者所不能及,可以配接、配接、再配接。这些配接操作包括系结(bind)、否定(negate),组合(compose)、以及对一般函数或成员函数的修饰(使其成为一个仿函数)。下图为count_if()和 bind2nd (less () , 12))的搭配实例。
在这里插入图片描述
这个搭配想要得到数组中所有小于12的数,具体流程为:

  1.从count_if函数中可以知道,它接受两个迭代器(begin()和end())以及一个函数对象,将每一个迭代器取值放入函数对象中进行处理;

  2.less()是一个仿函数,接受两个参数,判断参数1是否小于参数2。

template <class T>
struct less:public binar_function<T, T, bool> {bool operator()(const T& x, const T& y) const { return x < y;}
};

  3.bind2nd内部有一个binder2nd对象,binder2nd接受一个模板对象和这个模板对象的第二参数类型,其operator()为将输入的value绑定到模板对象的第二参数。最后将bind2nd对象传给count_if作为pred的参数,实现功能。

(1)not1、not2

  not1、not2的功能为接收一个仿函数对象作为参数,并对返回值进行逻辑否定,区别在于not1用于接受一元函数,not2用于接受二元函数。

//辅助函数,使我们得以方便使用 unary_negate<Pred>
template <class Predicateinline unary_negate<Predicate> notl(const Predicated pred) { return unary_negate<Piedicate>(pred);
}//以下配接器用来表示某个Adaptable Predicate的逻辑负值 (logical negation) 
template <class Predicateclass unary_negate:public unary_function<typename Predicate::arguement_typex bool> { 
protected:Predicate pred; / / 内部成员
public:explicit unary_negate(const Predicated x):pred(x) {}bool operator()(const typename Predicate::argument_type& x) const { return !pred(x); / / 将pred的运算结果加上否定(negate)运算}
};//辅助函数,使我们得以方便使用bineary_negate<Pred>
template<class Predicate>
inline binary_negate<Predicate> not2(const Predicated pred) { return binary_negate<Predicate>(pred);
}//以下配接器用来表示某个Adaptable Binary Predicate的逻辑负值 template <class Predicate>
class binary_negate:public binary_function<typename Predicate::first_argument_type, typename Predicate::second_argument_type, bool> {
protected:Predicate pred; // 内部成员
public:explicit binary_negate(const Predicated x) : pred(x) {}bool operator()(const typename Predicate::first_argument_type& const typename Predicate::second_arguinent_type& y) const {return !pred(x, y); //将pred的运算结果加上否定(negate)运算}
};

(2)bind1st、bind2nd

//辅助函数,让我们得以方便使用binderlst<Op> template <class Operation, class T>
inline binder1st<Operation> bind1st(const Operation& op, const T& x) {typedef typename Operation::first_argument_type argl_type;return binderlst<Operation>(op, argl_type(x));//以上,注意,先把x转型为op的第一参数型别
}template <class Operation>
class binder1st:public unary_function<typename Operation::second_argument_type, typename Operation::result_type> { 
protected:Operation op; // 内部成员typename Operation::first_argument_type value;// 内部成员
public:
// constructorbinder1st(const Operation& x, const typename Operation::first_argument_type& y):op (x),value (y) {} //将表达式和第一参数记录于内部成员typename Operation::result_typeoperator()(const typename Operation::second_argtunent_type& x) const {return op (value, x); //实际调用表达式,并将value绑定为第一参数
} );

  bind1st的功能是将一个二元函数转变为一元函数,他接受一个函数对象和一个函数对象第一参数类型的值,并将这个值绑定到函数对象的第一参数,返回这个函数对象的返回类型。

    std::less<int> lessThan;std::binder1st<std::less<int>> lessThan5 = std::bind1st(lessThan, 5);bool result = lessThan5(3);  // 相当于lessThan(5, 3)

  bind2nd与bind1st唯一区别在于,bind2nd将值绑定到对象的第二参数。

(3)compose1、compose2

已知两个一元函数f () , g (),配接器compose1用来产生一个h(), 使得h(x)= f(g(x)),即:

               conpose1( f () , g () )的效果等于f( g(x) )

//辅助函数,让我们得以方便运用 unary_compose<Opl,0p2>
template <class Operationl, class Operation2>
inline unary_compose<Operationl, Operation2> composel(const Operationl& opl, const Operation2& op2) {return unary_compose<Operationl, Operation2>(opl, op2);
}template <class Operationl, class Operation2>
class unary_compose:public unary_function<typename Operatioh2::argument^type, typename Operatiohl::result_type> { 
protected:Operationl op1; //内部成员Operation2 op2;// 内吾B成员
public:
// constructor
unary_compose(const Operationl& x, const 0peration2& y):opl (x) , op2 (y) {} / /将两个表达式记录于内部成员typename Operationl::result_typeoperator()(const typename Operations::ar0mnent_type& x) const {return opl (op2 (x) );// 函数合成
};

相应的,已知两个一元函数f () , g ()和一个二元函数h(),配接器compose2用来产生一个F(), 使得F(x)= H( f () , g () ),即:
               conpose2( H(), f () , g () )的效果等于H( f () , g () )

(4)ptr_fun

//辅助函数,让我们得以方便运用pointer_to_unary_function
template <class Arg, class Result>
inline pointer_to_unary_function<Arg, Result> ptr_fun(Result (*x)(Arg)) {return pointer_to_unary_function<Arg,Result>(x);
}//以下配接器其实就是把一个一元函数指针包起来:
//当仿函数被使用时,就调用该函数指针
template <class Arg, class Result>
class pointer_to_unary_function:public unary_functioi<Arg, Result> {
protected:Result (*ptr) (Arg);//内部成员,一个函数指针
public:pointer_to_unary_function() {}
//以下constructor将函数指针记录于内部成员之中explicit pointer_to_unary_function(Result (*x)(Arg)) : ptr(x) {}
//以下,通过函数指针执行函数Result operator()(Arg x) const { return ptr(x);} 
};

ptr_fun配接器其实就是把一个一元函数指针包起来,当仿函数被使用时,就调用该函数指针。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/259725.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

拼多多商品详情数据接口在数据分析行业的作用性

在数据分析行业中&#xff0c;拼多多商品详情数据的作用性主要体现在以下几个方面&#xff1a; 了解市场和用户需求&#xff1a;通过拼多多商品详情数据&#xff0c;企业可以了解到市场上什么产品受欢迎&#xff0c;用户对产品的反馈和评价如何&#xff0c;从而调整自己的销售…

项目优化(异步化)

项目优化&#xff08;异步化&#xff09; 1. 认识异步化 1.1 同步与异步 同步&#xff1a;一件事情做完&#xff0c;再做另外一件事情&#xff0c;不能同时进行其他的任务。异步&#xff1a;不用等一件事故完&#xff0c;就可以做另外一件事情。等第一件事完成时&#xff0c…

RocketMQ-RocketMQ高性能核心原理(流程图)

1.NamesrvStartup 2.BrokerStartup 3. DefualtMQProducer 4.DefaultMQPushConsumer

《每天一个Linux命令》 -- (5)通过sshkey密钥登录服务器

欢迎阅读《每天一个Linux命令》系列&#xff01;在本篇文章中&#xff0c;将介绍通过密钥生成&#xff0c;使用公钥连接管理服务器。 概念 SSH 密钥是用于安全地访问远程服务器的一种方法。SSH 密钥由一对密钥组成&#xff1a;公钥和私钥。公钥存储在远程服务器上&#xff0c;…

Hanlp自然语言处理如何再Spring Boot中使用

一、HanLP HanLP (Hankcs NLP) 是一个自然语言处理工具包&#xff0c;具有功能强大、性能高效、易于使用的特点。HanLP 主要支持中文文本处理&#xff0c;包括分词、词性标注、命名实体识别、依存句法分析、关键词提取、文本分类、情感分析等多种功能。 HanLP 可以在 Java、Py…

Nginx按指定格式记录访问日志

今天突然想起来一个日志的一个东西,因为拉项目无意中看到了日志文件的一些东西,现在不经常做后端了,加上其他的一些原因吧.有时候有些问题也没想太多,马马虎虎就过了,后来想想还是要记录一下这方面的处理过程吧: 一般我们作为开发人员关注的日志只是在应用程序层面的,我们称它…

网页设计--第6次课后作业

试用Vue相关指令完成对以下json数据的显示。显示效果如下&#xff1a; 其中&#xff1a;gender1 显示为女&#xff0c;gender2显示为男。价格超过30元&#xff0c;显示“有点小贵”。价格少于等于30元&#xff0c;则显示“价格亲民”。 data: {books: [{"id": "…

hook其他调试技巧

输出堆栈信息 通过 android.util.Log 输出当前线程的堆栈跟踪信息。 function showStacks() {Java.perform(function () {console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new() )); }) } 可以在需要的…

3GPP标准查看、下载和几个UE相关系列标准

由于一直做终端侧协议。最近以UE为核心重新下载了一系列文档。 总结并举例一下分类标准。 如何查看3GPP标准列表 实际上在3GPP网站如下链接&#xff1a;Specifications by Series&#xff0c;每个系列以及分类都说的很清楚。 几个系列分类举例 和终端协议层工作比较关系密切…

阿里云国际基于CentOS系统镜像快速部署Apache服务

阿里云轻量应用服务器提供了Windows Server系统镜像和主流的Linux系统镜像&#xff0c;您可以通过该类镜像创建纯净、安全、稳定的运行环境。本文以CentOS 7.6系统镜像为例&#xff0c;介绍如何快速配置Apache服务。 背景信息 注意&#xff0c;阿里云国际通过corebyt注册并充…

Spring Boot 整合 xxl-job 保姆级教程!

文章目录 介绍使用初始化“调度数据库”配置调度中心配置“执行器项目”调度任务 介绍 首先我们介绍一下什么是xxl-job&#xff0c;根据官方定义&#xff0c;XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码…

LeetCode(52)最小栈【栈】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 最小栈 1.题目 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void…