【STL十四】函数对象(function object)_仿函数(functor)——lambda表达式
【STL十四】函数对象(function object)_仿函数(functor)——lambda表达式
- 一、函数对象(function object)
- 二、函数对象优点
- 三、分类
- 四、头文件
- 五、用户定义函数对象demo
- 六、std::内建函数对象
- 1、 算术运算函数对象
- 2、比较
- 3、逻辑运算
- 4、位运算
- 七、lambda表达式
- 1、简介
- 2、作用
- 3、定义
- 4、最简单的demo
- 5、标准用法
- 6、变量捕获(capture clause)
一、函数对象(function object)
- 定义:定义了一个operator()的对象,就叫函数对象(function object)。
- 函数对象又被叫做仿函数(functor)。
注意:
- 函数对象是一个类(or结构体、模板类),不是一个函数。
- 函数对象重载“()”操作符,使得类可以像函数那样调用。
安装参数分
如果函数对象,有一个参数,叫一元函数对象。
如果函数对象,有二个参数,叫二元函数对象。
如果函数对象,有三个参数,叫多元函数对象。
二、函数对象优点
- 函数对象通常不定义构造函数和析构函数,所以在构造和析构不会发生问题
- 函数对象可以有自己的状态;(超出了普通函数的概念)
- 模板函数对象使得函数对象具有通用性。
三、分类
- 用户定义函数对象
- std::内置函数对象
- lambda表达式
四、头文件
- 用户自己定义的函数无头文件,
- std内建函数对象
头文件如下
// 内置函数对象
#include<functional>
五、用户定义函数对象demo
- Print就是函数对象
- Print()(“HELLO WORLD”);//匿名函数对象
#include <iostream>
//
using namespace std;class Print
{
public:void operator()(const char str[]){cout << str << endl;}
};int main() {Print ob;ob("hello world");Print()("HELLO WORLD");//匿名函数对象}
输出
hello world
HELLO WORLD
- 函数对象可以有自己的状态?
demo
#include <iostream>
//#include<functional>
using namespace std;class Print
{
public:void operator()(const char str[]){cout << str << endl;m_sum++;}int m_sum = 0;
};int main() {Print ob;ob("hello world");ob("hello jx");cout << ob.m_sum << endl;}
输出
hello world
hello jx
2
-
当然以上你可以写成模板,or同时重载int类型的,都是可以的
- 重载int类型的
#include <iostream>
//#include<functional>
using namespace std;struct Print
{
public:void operator()(const char str[]){cout << str << endl;}void operator()(int num){cout << num << endl;}
};int main() {Print ob;ob("hello world");Print()("HELLO WORLD");ob(110);}
- 模板函数对象使得含对象具有通用性?
- 模板
#include <iostream>
#include<string>
using namespace std;template<typename T>
class Print
{
public:void operator()(T temp){cout << temp << endl;m_sum++;}int m_sum = 0;
};int main() {Print<string> ob;ob("hello world");ob("hello jx");cout << ob.m_sum << endl;Print<int> ob2;ob2(123);ob2(123);
}
输出
hello world
hello jx
2
123
123
六、std::内建函数对象
- stl内建了一些函数对象,分为算术运算、比较、逻辑运算、位运算;
- 其实,这些内建函数对象,都是配合容器和算法使用的,但是我们还没有讲解郭算法,所以做个不设计算法的简单的demo.
1、 算术运算函数对象
- 1.1、分类

- 1.2、demo
#include <iostream>
#include<functional>
using namespace std;int main() {std::plus<int> add;cout << "add(2, 3) = " << add(2, 3) << endl; //2+3 = 5std::minus<int> sub;cout << "sub(2, 3) = " << sub(2, 3) << endl; //2-3 = -1std::multiplies<int> mul;cout << "mul(2, 3) = " << mul(2, 3) << endl; //2*3 = 6std::divides<int> div;cout << "div(2, 3) = " << div(2, 3) << endl; //2/3 = 0std::modulus<int> mod;cout << "mod(2, 3) = " << mod(2, 3) << endl; //2%3 = 2std::negate<int> neg;cout << "neg(2) = " << neg(2) << endl; //neg(2) = -2 }
输出
add(2, 3) = 5
sub(2, 3) = -1
mul(2, 3) = 6
div(2, 3) = 0
mod(2, 3) = 2
neg(2) = -2
2、比较
- 2.1、分类

- 2.2、demo
#include <iostream>
#include<functional>
using namespace std;int main() {std::equal_to<int> ob1;cout << "ob1(1, 2) = " << ob1(1, 2) << endl;std::not_equal_to<int> ob2;cout << "ob2(1, 2) = " << ob2(1, 2) << endl;std::greater<int> ob3;cout << "ob3(1, 2) = " << ob3(1, 2) << endl;std::less<int> ob4;cout << "ob4(1, 2) = " << ob4(1, 2) << endl;std::greater_equal<int> ob5;cout << "ob5(1, 2) = " << ob5(1, 2) << endl;std::less_equal<int> ob6;cout << "ob6(1, 2) = " << ob6(1, 2) << endl;
}
输出
ob1(1, 2) = 0
ob2(1, 2) = 1
ob3(1, 2) = 0
ob4(1, 2) = 1
ob5(1, 2) = 0
ob6(1, 2) = 1
3、逻辑运算
- 3.1、分类

- 3.2、demo
#include <iostream>
#include<functional>
using namespace std;int main() {std::logical_and<bool> l_and;cout << "l_and(1, 0) = " << l_and(1, 0) << endl;std::logical_or<int> l_or;cout << "l_or(1, 0) = " << l_or(1, 0) << endl; std::logical_not<int> l_not;cout << "l_not(2) = " << l_not(2) << endl;
}
输出
l_and(1, 0) = 0
l_or(1, 0) = 1
l_not(2) = 0
4、位运算
- 4.1、分类
- demo
- 1、“与” 运算(&):只有两个位都是1的时候结果才是1,否则是0;如1&1=1,1&0=0,0&1=0,0&0=0
- 2、“或” 运算(|):只要有一个是1,结果就是1。如:1|0=1,0|1=1,1|1=1,0|0=0
- 3、“异或” 运算(^):相同为0,不同为1;0|0=0,0|1=1,1|0=1,1|1=0
- 4、取反运算(~):就是0=1,1=0
#include <iostream>
#include<functional>
using namespace std;int main() {std::bit_and<int> b_and;cout << "b_and(1, 2) = " << b_and(1, 2) << endl;std::bit_or<int> b_or;cout << "b_or(1, 2) = " << b_or(1, 2) << endl;std::bit_xor<int> b_xor;cout << "b_xor(2,3) = " << b_xor(2,3) << endl;std::bit_not<bool> b_not;cout << "b_not(1) = " << b_not(1) << endl;
}
输出
b_and(1, 2) = 0
b_or(1, 2) = 3
b_xor(2,3) = 1
b_not(1) = 1
bit_not有问题,因为bool的取反,应该是0,但是输出是1,原因未知;
七、lambda表达式
使用 STL 时,往往会大量用到函数对象,为此要编写很多函数对象类。有的函数对象类只用来定义了一个对象,而且这个对象也只使用了一次,编写这样的函数对象类就有点浪费。
而且,定义函数对象类的地方和使用函数对象的地方可能相隔较远,看到函数对象,想要查看其 operator() 成员函数到底是做什么的也会比较麻烦。
- 对于只使用一次的函数对象类,能否直接在使用它的地方定义呢?Lambda 表达式能够解决这个问题。使用 Lambda 表达式可以减少程序中函数对象类的数量,使得程序更加优雅。
1、简介
- lambda expressions = lambda表达式(也叫闭包——Colsure)
- lambda表达式也是匿名函数对象
- lambda表达式也是一种仿函数、
2、作用
- 很方便的定义函数、并被别的函数调用。
3、定义
Lambda 表达式的定义形式如下:
[]中括号里面是一下捕获变量,或者为空。
[捕获变量] (参数表) -> 返回值类型
{函数主体
}auto f=[](int a, int b) ->int
{
return a+b;
};
“捕获变量”可以是=或&,表示{}中用到的、定义在{}外面的变量在{}中是否允许被改变。=表示不允许,&表示允许。当然,在{}中也可以不使用定义在外面的变量。“-> 返回值类型”可以省略。
4、最简单的demo
#include <iostream>
#include<vector>
#include<functional>
using namespace std;int main() {auto f = [](int a, int b){return a < b;};cout << f(2, 3);
}
输出
1
5、标准用法
#include <iostream>
#include<vector>
#include<functional>
using namespace std;int main() {// 定义lambda表达式,不使用变量捕获auto f = [](int a, int b) ->int{return a + b;};cout << f(1, 2) << endl;
}
输出
3
6、变量捕获(capture clause)
#include <iostream>
#include<vector>
#include<functional>
using namespace std;int main() {int M = 10;int N = 3;auto f = [&M, N](int a) ->int{M = 20;return N*a;};cout << f(3) << endl;cout << M << endl;
}
输出
9
20
- 变量捕获:就是方括号中的部分,让我们的匿名函数可以访问、甚至修改函数外部的变量。
- 如果是空,表示不捕获任何变量。
- [&M]——如果变量前有引用&,则是按引用捕获——可以修改外围变量的值。
- [M]——如果变量前没引用&,则是按值捕获——不可以修改外围变量的值。
- [&]——只写引用,按照引用捕获所有的封闭范围中的变量;
- [=]——只写等号,所有变量都按值捕获;
- [&, = M]——单独制定一些变量按照值捕获,其他变量按照引用捕获;
- [this]——如果在某个class中使用匿名函数,可以使用this捕获当前实例的指针。
- c++17后还可以使用[*this]按值捕获该实例。
- c++14后,可以在捕获语句中定义新的变量,并初始化。(这些变量无需出现在匿名函数外围环境中)
auto f = [&M, N, k=5](int a) ->int{M = 20;return N*a*k;};
- c++14后,参数列表支持auto类型
[](auto a, auto b){return a+b;}
参考:
1、C++ STL 容器库 中文文档
2、STL教程:C++ STL快速入门
3、https://www.apiref.com/cpp-zh/cpp/header.html
4、https://en.cppreference.com/w/cpp/container
5、哔哩哔哩_HexUp_清晰易懂,现代C++最好用特性之一:Lambda表达式用法详解
6、WIKI教程_C ++标准库_C++ Library - <iterator>
相关文章:
【STL十四】函数对象(function object)_仿函数(functor)——lambda表达式
【STL十四】函数对象(function object)_仿函数(functor)——lambda表达式 一、函数对象(function object)二、函数对象优点三、分类四、头文件五、用户定义函数对象demo六、std::内建函数对象1、 算术运算函…...
如何写出高质量的前端代码
写出高质量的前端代码是每个前端开发人员的追求。在一个复杂的项目中,代码质量对于项目的可维护性、可扩展性和可读性都有很大的影响。本文将介绍一些如何写出高质量前端代码的技巧和最佳实践。 一、注重代码结构和组织 1.1 遵循一致的命名规范 命名规范是编写高…...
YOLOv7如何提高目标检测的速度和精度,基于优化算法提高目标检测速度
目录 一、学习率调度二、权重衰减和正则化三、梯度累积和分布式训练1、梯度累积2、分布式训练 四、自适应梯度裁剪 大家好,我是哪吒。 上一篇介绍了YOLOv7如何提高目标检测的速度和精度,基于模型结构提高目标检测速度,本篇介绍一下基于优化算…...
CentOS 7中安装配置Nginx的教程指南
1. 安装Nginx 在终端中执行以下命令以安装Nginx: sudo yum install epel-release sudo yum install nginx安装完成后的 Nginx 内容通常会被安装在以下目录下: /etc/nginx: 该目录包含 Nginx 的配置文件,包括 nginx.conf 和 conf.d 目录下的…...
Vicuna- 一个类 ChatGPT开源 模型
Meta 开源 LLaMA(大羊驼)系列模型为起点,研究人员逐渐研发出基于LLaMA的Alpaca(羊驼)、Alpaca-Lora、Luotuo(骆驼)等轻量级类 ChatGPT 模型并开源。 google提出了一个新的模型:Vicuna(小羊驼)。该模型基于LLaMA,参数量13B。Vicuna-13B 通过微调 LLaMA 实现了高性能…...
5.1 数值微分
学习目标: 作为数值分析的基础内容,我建议你可以采取以下步骤来学习数值微分: 掌握微积分基础:数值微分是微积分中的一个分支,需要先掌握微积分基础知识,包括导数、极限、微分等。 学习数值微分的概念和方…...
云计算服务安全评估办法
云计算服务安全评估办法 2019-07-22 14:46 来源: 网信办网站【字体:大 中 小】打印 国家互联网信息办公室 国家发展和改革委员会 工业和信息化部 财政部关于发布《云计算服务安全评估办法》的公告 2019年 第2号 为提高党政机关、关键信息基础设施运营者…...
laravel5.6.* + vue2 创建后台
本地已经安装好了composer 1.新建 Laravel5.6.*项目 composer create-project --prefer-dist laravel/laravel laravel5vue2demo 5.6.* 2. cd laravel5vue2demo 3. npm install /routes/web.php 路由文件中, 修改 Route::get(/, function () {return view(index); });新建…...
Python自动化sql注入:布尔盲注
在sql注入时,使用python脚本可以大大提高注入效率,这里演示一下编写python脚本实现布尔盲注的基本流程: 演示靶场:sqli-labs 布尔盲注 特点:没有回显没有报错,但根据sql语句正常与否返回不同结果&#x…...
Microsoft Defender for Office 365部署方案
目录 前言 一、Microsoft Defender for Office 365 部署架构 1、部署环境 2、Microsoft Defender for Office 365 核心服务...
字节岗位薪酬体系曝光,看完感叹:不服真不行
曾经的互联网是PC的时代,随着智能手机的普及,移动互联网开始飞速崛起。而字节跳动抓住了这波机遇,2015年,字节跳动全面加码短视频,从那以后,抖音成为了字节跳动用户、收入和估值的最大增长引擎。 自从字节…...
华为OD机试-高性能AI处理器-2022Q4 A卷-Py/Java/JS
某公司研发了一款高性能AI处理器。每台物理设备具备8颗AI处理器,编号分别为0、1、2、3、4、5、6、7。 编号0-3的处理器处于同一个链路中,编号4-7的处理器处于另外一个链路中,不同链路中的处理器不能通信。 现给定服务器可用的处理器编号数组…...
Vue - 实现垂直菜单分类栏目,鼠标移入后右侧出现悬浮二级菜单容器效果(完整示例源码,详细代码注释,一键复制开箱即用)
前言 网上的教程都太乱了,各种杂乱无注释代码、图片资源丢失、一堆样式代码,根本无法改造后应用到自己的项目中。 本文实现了 在 Vue / Nuxt 项目中,垂直分类菜单项,当用户鼠标移入菜单后,右侧自动出现二级分类悬浮容器盒子效果, 您可以直接复制源码,然后按照您的需求再…...
NVM-无缝切换Node版本
NVM-无缝切换Node版本 如果未使用nvm之前已经下载了node,并且配置了环境变量,那么此时删除这些配置(Node的环境以及Node软件),使用nvm是为了在某些项目中使用低版本的node NVM下载 进入github的nvm readme: https://github.com/coreybutler/nvm-windows…...
CCF-CSP真题《202303-1 田地丈量》思路+python,c++满分题解
想查看其他题的真题及题解的同学可以前往查看:CCF-CSP真题附题解大全 试题编号:202303-1试题名称:田地丈量时间限制:1.0s内存限制:512.0MB问题描述: 问题描述 西西艾弗岛上散落着 n 块田地。每块田地可视为…...
Autosar-软件架构
文章目录 一、Autosar软件架构分层图二、应用层三、RTE层四、BSW层1、微控制器抽象层2、ECU抽象层I/O硬件抽象COM硬件抽象Memory硬件抽象Onboard Device Abstraction3、复杂驱动层4、服务层系统服务通信服务CAN一、Autosar软件架构分层图 架构分层是实现软硬件分离的关键,它也…...
8年测开年薪30W,为什么从开发转型为测试?谈谈这些年的心路历程……
谈谈我的以前,从毕业以来从事过两个多月的Oracle开发后转型为软件测试,到现在已近过去8年成长为一个测试开发工程师,总结一下之间的心路历程,希望能给徘徊在开发和测试之前的同学一点小小参考。 一、测试之路伏笔 上学偷懒&#…...
滑动奇异频谱分析:数据驱动的非平稳信号分解工具(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
updateByPrimaryKey和updateByPrimaryKeySelective的区别
版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl MyBatis Generator概述 MyBatis Generator是一个专门为MyBatis框架使用者定制的代码生成器,它可以快速的根据表生成对应的映射文件、接口文件、POJO。而且&#…...
【ARM Coresight 4 - Rom Table 介紹】
文章目录 1.1 ROM Table1.1.1 Entry 寄存器 1.2 ROM Table 例子 1.1 ROM Table 在一个SoC中,有多个Coresight 组件,但是软件怎么去识别这些 Coresight 组件,去获取这些Coresight 组件的信息了?这个时候,就需要靠 Core…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
uniapp 小程序 学习(一)
利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 :开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置,将微信开发者工具放入到Hbuilder中, 打开后出现 如下 bug 解…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
鸿蒙HarmonyOS 5军旗小游戏实现指南
1. 项目概述 本军旗小游戏基于鸿蒙HarmonyOS 5开发,采用DevEco Studio实现,包含完整的游戏逻辑和UI界面。 2. 项目结构 /src/main/java/com/example/militarychess/├── MainAbilitySlice.java // 主界面├── GameView.java // 游戏核…...
