C++、STL标准模板库和泛型编程 ——迭代器、 算法、仿函数(侯捷)

news/2024/4/26 18:08:52/文章来源:https://blog.csdn.net/weixin_43412762/article/details/130232183

C++、STL标准模板库和泛型编程 ——迭代器、 算法、仿函数 (侯捷)

  • 迭代器
    • iterator_category
  • 算法
    • accumulate
    • for_each
    • replace
    • count
    • find
    • sort
    • binary_search
  • 仿函数 functors(六大部件中最简单的一种!)

使用一个东西,却不明白它的道理,不高明!—— 林语堂

阶段学习
使用C++标准库
认识C++标准库(胸中自有丘壑!)
良好使用C++标准库
扩充C++标准库

所谓 Generic ProgrammingGP,泛型编程),就是使用 template (模板)为主要工具来编写程序。

  • GP 是将 datasmethods 分开来;

    • ContainersAlgorithms可各自闭门造车﹐其间以Iterator连通即可·
    • Algorithms通过Iterators确定操作范围﹐也通过Iterators取用 Container元素。
  • OOP(Object-Oriented Programming),企图将 datasmethods 关联在一起。

C++标准模板库Standard Template 最重要的六大部件(Components):容器算法仿函数迭代器适配器分配器

  • 容器(Containers)是class template
  • 算法(Algorithms)是function template其内最终涉及元素本身的操作,无非就是比大小!)
  • 迭代器(Iterators)是class template
  • 仿函数(Functors)是class template
  • 适配器(Adapters)是class template
  • 分配器(Allocators)是class template

关系图:
在这里插入图片描述

迭代器

前面说到迭代器中必须要有5种关联类型:pointerreferenceiterator_category(迭代器类型,比如说随机存取)、value_type(值存放类型)、difference_type(容器两个元素之间的距离类型)。

iterator_category

也有五种迭代器类型:随机存取迭代器arrayvectordeque)、双向迭代器list红黑树容器)、单向迭代器forward_listhash类容器)、输入迭代器istream迭代器),输出迭代器ostream迭代器)。

在这里插入图片描述
既然是tag,为什么要用有继承关系的class来实现呢?

  • 方便迭代器类型作为参数进行传递,如果是整数的是不方便的;还有一个原因,有些算法的实现没有实现特定类型的迭代器类别,就可以用继承关系去找父迭代器类别。

在这里插入图片描述
iterator_category对算法的影响

以这个distance函数为例,会根据迭代器的类别来调用不同的具体实现函数,

  • 一个是只包含一个减法操作的语句,
  • 一个是包含一个while循环的语句,可想而知,当真实距离很大时,有while循环的具体实现函数效率会非常低下。

使用萃取机iterator_traits,虽然只有两种,但是这几种类型都是继承关系is a 父类input_iterator_tag,如果没有重载,最终都会落到input_iterator_tag

在这里插入图片描述

看一个特别能体现C++注重效率的体现:
copy实现,到最终的实现细节,经过了很多判断,这些判断是为了找到最高效率的实现,就是判断迭代器的分类。

在这里插入图片描述
在这里插入图片描述

算法

Algorithms看不见Containers,对其一无所知;所以,它所需要的一切信息都必须从Iterators取得,而Iterators(由Containers供应)必须能够回答Algorithm的所有提问,才能搭配该Algorithm的所有操作。

template<typename Iterator>
Algorithm(Iterator it1, Iterator it2){...
}template<typename Iterator, typename Cmp>//Cmp为传入的一个准则,比如比大小准则
Algorithm(Iterator it1, Iterator it2, Cmp comp){...
}

accumulate

template<class InputInterator, class T>
T accumulate(InputIterator first, InputIterator last, T init){...}//另外一个版本为:
template<class InputInterator, class T, class BinaryOperation>
T accumulate(InputIterator first, InputIterator last, T init, BinaryOperation binary_op){...}

上面这个binary_op指明是一个二元操作数的函数,可以是仿函数(实质上是一个类),也可以是函数,只要是能够在该算法的函数体内通过小括号调用就行!!!!

  • 也就是能够这么用:binary_op(a, b);
  • 就算是在算法(函数)里面,也能够使用仿函数,但是传入的是仿函数的对象实例,而如果要传入函数的话,就传函数名就可以了。
int init = 100;
int nums[] = {10,20,30};
accumulate(nums, nums+3, init);//不指定具体怎么操作,默认为加法,输出160
accumulate(nums, nums+3, init, minus<int>()); //这minus时减法的意思,所以输出为40

for_each

  • 对容器区间内的元素做同样的事情。
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f){...}

replace

1、 replace

  • 将容器区间内的元素进行替换,如果元素值等于old_value就把它替换为new_value.
template<class ForwardIterator, class T>
void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value){...}

2、replace_if

  • 在算法中看到 if ,就代表你要给他一个条件。
  • Predicate为一个条件,判断式子(传回),如果符合条件就进行替换
template<class ForwardIterator, class Predicate, class T>
void replace_copy(ForwardIterator first, ForwardIterator last,  Predicate pred, const T& new_value){...}

3、replace_copy

  • 范围内所有等同于old_value的都以new_value放置新的区间中,不符合原值的也放入新的区间
template<class InputIterator, class OutputIterator, class T>
OutputIterator replace_copy(InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value)
{...}

count

容器不带成员函数count():

array, vector, list, forward_list, deque

容器带有成员函数count()红黑树hash容器中有自己的count):

set /multiset
map / multimap
unordered_set / unordered_multiset
unordered_map / unordered_multimap

1、count

  • 区间内有和value相等的元素count + 1
template<class InputIterator, class T>
typename iterator_traits<InputIterator>::difference_type
count(InputIterator first, InputIterator last, const T& value){...}

2、count_if

  • 区间内有符合pred条件的 count + 1
template<class InputIterator, class Predicate>
typename iterator_traits<InputIterator>::difference_type
count_if(InputIterator first, InputIterator last, Predicate pred){...}

find

容器不带成员函数find():

array, vector, list, forward_list, deque

容器带有成员函数find()红黑树hash容器中有自己的find):

set /multiset
map / multimap
unordered_set / unordered_multiset
unordered_map / unordered_multimap

1、find

  • 循序查找,返回第一个和value相等的迭代器
template<class InputIterator, class T>
InputIterator find(InputIterator first, InputIterator last, const T& value){...}

1、find_if

  • 循序查找,查找符合条件的第一个元素的迭代器
template<class InputIterator, class Predicate>
InputIterator find_if(InputIterator first, InputIterator last, Predicate pred){...}

sort

  • sort要求RandomAccessIterator

容器不带成员函数sort():

array, vector, deque//已经排序,遍历自然形成sorted状态
set /multiset
map / multimap
unordered_set / unordered_multiset
unordered_map / unordered_multimap

容器带有成员函数sort():下面这两种容器都不能 " "

list, forward_list

sort

  • 默认从小到大排序,也可以指定自己的比较函数,可以是仿函数,可以是函数,仿函数必须传入该仿函数的实例。
sort(InputIterator first, InputIterator last, Function f)

binary_search

  • 一定是在已排序状态下
  • 源码中就是调用lower_bound
template<class ForwardIterator, class T>
bool binary_search(ForwardIterator first, ForwardIterator last, const T& value){...}

在这里插入图片描述

lower_bound(ForwardIterator first, ForwardIterator last, T target)
upper_bound(ForwardIterator first, ForwardIterator last, T target)

lower_bound二分查找的一个版本,如果找到对应的值,则返回指向其中第一个元素的迭代器,如果不存在,则返回最适合安插这个target的点的迭代器 ,也就是说它返回迭代器指向第一个不小于target的元素,返回的是不破坏排序得以安插target的第一个适当位置。

仿函数 functors(六大部件中最简单的一种!)

  • 只为算法而服务!
  • class模仿函数,必须要重载小括号()

有三大类,大该至少共有24个仿函数:

  • 算术类+-*/ 等);
  • 逻辑运算类&&|| 等);
  • 相对关系类(返回 bool )。

算术类:(Arithmetic)

template<class T>
struct plus : public binary_function<T, T, T>{T operator()(const T& x, const T& y) const{return x + y;}
};template<class T>
struct minus : public binary_function<T, T, T>{T operator()(const T& x, const T& y) const{return x - y;}
};...

逻辑运算类:(Logical)

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

相对关系类:(Relational)

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

使用例子:

//using explicitly default comparison(operator <):
sort(myvec.begin(), myvec.end(), less<int>());

为什么要把它们设计成仿函数呢?

  • 因为要传入算法!要把它们作为参数

上面的列举的几个都继承binary_function,说明有两个操作数,为什么要让仿函数继承这些类呢?

  • 首先,继承他们,不会增加仿函数的内存大小;
  • 其次,继承了他们,会有了first_argument_type等的typedef,后续可以根据这个类型进行一些修改。
  • 以及仿函数(functors)的可适配(adaptable)条件:STL规定每个Adaptable Function都应挑选适当地继承unary_fucntionbinary_function等类,才能融入到STL中,才能回答适配器的问题 (就像Traits机要回答迭代器的问题一样)。

unary_fucntionbinary_function的定义:

//一个操作数(例如 对一个值取反)
template<class Arg, class Result>
struct unary_fucntion{//理论上大小为0,(sizeof为1)typedef Arg argument_type;typedef Result result_type;
}//两个操作数
template<class Arg1, class Arg2, class Result>
struct bianry_fucntion{//理论上大小为0,(sizeof为1)typedef Arg1 first_argument_type;typedef Arg2 second_argument_type;typedef Result result_type;
}

注:仅供学习参考,如有不足,欢迎指正!

觉得有帮助的话,点个赞呗(^ - ^)!

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

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

相关文章

4月21日第壹简报,星期五,农历三月初二

4月21日第壹简报&#xff0c;星期五&#xff0c;农历三月初二坚持阅读&#xff0c;静待花开1. 推特拒向大模型免费开放数据&#xff01;马斯克威胁起诉微软&#xff1b;Reddit宣布不再向大模型免费开放数据&#xff0c;要求科技巨头付费使用API接口。2. 浙江&#xff1a;鼓励杭…

2023.04.24 c++第六讲

作业&#xff1a; 1. 手动实现顺序栈&#xff0c;要求实现数据结构中&#xff0c;所有栈的相关操作 #include <iostream> #define MAXSIZE 20 //宏定义&#xff0c;栈的最大容量 using namespace std;template <typename T> class stacklink { pri…

FBEC大会 | 瑞云科技 CTO 赵志杰:元宇宙时代的基础设施——实时云渲染

​ FBEC未来商业生态链接大会于2023年2月24日在深圳福田大中华喜来登酒店盛大召开&#xff0c;本次大会由广东省游戏产业协会、深圳市互联网文化市场协会指导&#xff0c;陀螺科技主办。 大会以“勇毅前行逐光而上”为主题&#xff0c;以具有行业前瞻洞察的“探索者”为视角&a…

Three.js+TypeScript+Webpack学习记录(二)

使用环境参考 Node.js v16.19.1 正文 跟着文档画个线 看看 Three 的官方文档&#xff0c;起步 -> 画线 -> 没了&#xff1f;&#xff01;&#xff01; 不管怎么说&#xff0c;先画个线吧。 import * as THREE from threeconst scene new THREE.Scene() const camer…

PyTorch深度学习实战 | 基于深度学习的电影票房预测研究

基于深度学习的映前票房预测模型(Cross&Dense网络结构模型)&#xff0c;该模型通过影片基本信息如&#xff1a;电影类型、影片制式、档期和电影的主创阵容和IP特征等信息对上映影片的票房进行预测。 本篇采用451部电影作为训练模型&#xff0c;最后再在194部影片上进行测试…

【计网 从头自己构建协议】一、libpcap 介绍 手撕以太网帧

上一篇&#xff1a;IndexError: list index out of range 下一篇&#xff1a;[【计网 从头自己构建协议】二、收发 ARP 请求帧与响应帧] 介绍 理论的学习总是枯燥的&#xff0c;想要加深对理论的理解&#xff0c;最好的方法就是自己实践一遍。 想要亲手实现各种协议&#xf…

【音视频第17天】RTSP、RTMP协议初识

被叫去搞直播了&#xff0c;悲喜交加。先学习一下基本的技术栈&#xff0c;RTSP RTMP HTTP 先简单随便看看吧。 目录 什么是流媒体协议RTMPRTMP 工作原理 RTSPRTSP 工作原理 RTMP 与 RTSP 区别详细看看RTSP简介RTSP交互流程OPTIONSDESCRIBESETUPPLAYPAUSESET_PARAMETERGET_PAR…

春招,进阿里了....

个人背景是东北某 985 科班本硕&#xff0c;做的 测试开发&#xff0c;有两个自己写的小项目。下面是一些印象比较深刻的面试题 阿里一面 什么是软件测试&#xff1f; 软件测试过程中会面向哪些群体&#xff1f; 开发一个软件都要经过哪些阶段&#xff1f; 什么是黑盒测试&…

八年软件测试生涯,是时候做出改变了

五年前&#xff0c;我在南方的大城市&#xff1a;广州&#xff0c;做着一个快乐的游戏测试&#xff0c;工作不太忙&#xff0c;对一切技术充满了好奇心。测试工作不专业&#xff0c;也不受重视。但我有自己的快乐。工作不忙的时候&#xff0c;我今天学学Python&#xff0c;明天…

什么是客户服务平台?

在社交媒体和智能手机出现之前&#xff0c;品牌主要通过单向广告渠道与客户互动。社交媒体打破了这种自上而下的动态&#xff0c;以前所未有的方式打开了对话&#xff0c;将客户包括在内。 品牌不再控制客户对人们分享公司内容的行为。人们可以点击离开&#xff0c;向左滑动&a…

Python-pyppeteer解决微软Microsoft的登录机器人验证(8)

前言 本文是该专栏的第8篇,结合优质项目案例,让你精通使用Pyppeteer,后面会持续分享Pyppeteer的干货知识,记得关注。 在注册微软Microsoft账号或者注册outlook邮箱账号的时候,会遇到如下机器人验证: 是的,你可能第一眼看到这个验证页面,首先会想到是定位它的页面元素N…

非常详细的阻抗测试基础知识

编者注&#xff1a;为什么要测量阻抗呢&#xff1f;阻抗能代表什么&#xff1f;阻抗测量的注意事项... ...很多人可能会带着一系列的问题来阅读本文。不管是数字电路工程师还是射频工程师&#xff0c;都在关注各类器件的阻抗&#xff0c;本文非常值得一读。全文13000多字&#…

Vue CLI 服务

使用命令 在一个 Vue CLI 项目中&#xff0c;vue/cli-service 安装了一个名为 vue-cli-service 的命令。你可以在 npm scripts 中以 vue-cli-service、或者从终端中以 ./node_modules/.bin/vue-cli-service 访问这个命令。 这是你使用默认 preset 的项目的 package.json&…

电脑突然变成绿屏错误代码无法使用怎么办?

电脑突然变成绿屏错误代码无法使用怎么办&#xff1f;有用户使用电脑的时候&#xff0c;电脑桌面变成了绿屏的显示&#xff0c;所有的操作无法继续进行。遇到这个问题要怎么去进行解决呢&#xff1f;来看看详细的解决方法教学吧。 准备工作&#xff1a; 1、U盘一个&#xff08;…

(原创)Flutter基础入门:手把手教你搭建Flutter混合项目

前言 Flutter是Google开源的构建用户界面&#xff08;UI&#xff09;工具包 支持在不同平台构建一致的ui效果 但在实际业务中&#xff0c;一般不会整个APP都用纯Flutter开发 尤其一些老的项目&#xff0c;会采用接入Flutter的方式来混合开发 那么今天就主要讲一下如何搭建一个…

SQLServer:Win/Linux环境安装及一键部署脚本

1. Win安装SQLServer CSDN已有完整安装流程&#xff0c;亲测可用。----》Windows安装SQLServer流程 2. Linux安装 SQLServer 2.1 设置镜像 curl https://packages.microsoft.com/config/rhel/7/mssql-server-2017.repo > /etc/yum.repos.d/mssql-server.repo 2.2 通过y…

深度学习模型参数量与训练数据量的平衡对泛化性能的影响

一、引言 深度学习模型在计算机视觉、自然语言处理等领域取得了显著的成果。为了获得泛化性能良好的模型&#xff0c;研究者需要在模型复杂度和训练数据量之间找到合适的平衡。本文将探讨这两者之间的关系以及如何在实际应用中实现最佳效果。 二、模型复杂度与训练数据量的关…

史上最严宝宝口粮新国标出台,DHA和维生素D可能无需额外补充了

自2023年2月22日起&#xff0c;我国婴幼儿配方食品&#xff08;以下简称配方奶&#xff09;新国标开始实施。这意味着2023年2月22日以后在中国上架销售的配方奶必须符合新国标&#xff0c;重新取得国家市场监督管理总局食品评审中心&#xff08;CFE-SAMR&#xff09;的注册。这…

改变思想,拥抱毒瘤,让公司走的更远

牛B的人物&#xff0c;早已经厌倦了中英文混杂&#xff0c;他们更进一步&#xff0c;使用中英文缩写&#xff0c;对普通人进行降维打击。更厉害的&#xff0c;造就新的名词&#xff0c;并科普出去。 有几项技术&#xff0c;我从心底里鄙视和厌恶&#xff0c;但每次在技术方案中…