C++学习记录——이십팔 C++11(4)
文章目录
- 包装器
- 1、functional
- 2、绑定
这一篇比较简短,只是因为后要写异常和智能指针,所以就把它单独放在了一篇博客,后面新开几篇博客来写异常和智能指针
包装器
1、functional
包装器是一个类模板,对可调用对象类型进行再封装适配,可调用对象,比如函数指针,lambda等。包装器的头文件是functional。
template <class T> function;
template <class Ret, class... Args>
class function<Ret(Args...)>
模板参数说明:
Ret:被调用函数的返回类型
Args...:被调用函数的形参
实际使用
int f(int a, int b)
{cout << "f" << endl;return a + b;
}struct Functor
{
public:int operator() (int a, int b){cout << "Functor" << endl;return a + b;}
};int main()
{//int(*pf1)(int, int) = f;函数指针function<int(int, int)> f1 = f;function<int(int, int)> f2 = Functor();function<int(int, int)> f3 = [](int a, int b) {cout << "lambda" << endl;return a + b; };cout << f1(1, 2) << endl;cout << f2(10, 20) << endl;cout << f3(100, 200) << endl;return 0;
}
三个int,第一个是函数返回值类型,后两个是参数类型。包装起包装起来的就可以传给模板参数
map<string, function<int(int, int)>> opFuncMap;opFuncMap["函数指针"] = f1;opFuncMap["仿函数"] = Functor();opFuncMap["lambda"] = [](int a, int b) {cout << "lambda" << endl;return a + b;};cout << opFuncMap["lambda"](1, 2) << endl;
看一个题
逆波兰表达式求值
给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
有效的算符为 ‘+’、‘-’、‘*’ 和 ‘/’ 。
每个操作数(运算对象)都可以是一个整数或者另一个表达式。
两个整数之间的除法总是 向零截断 。
表达式中不含除零运算。
输入是一个根据逆波兰表示法表示的算术表达式。
答案及所有中间计算结果可以用32位整数表示。


之前的写法
class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> st;for(auto& str : tokens){if(str == "+" || str == "-" || str == "/" || str == "*"){int right = st.top();st.pop();int left = st.top();st.pop();switch(str[0]){case '+':st.push(left+right);break;case '-':st.push(left-right);break;case '*':st.push(left*right);break;case '/':st.push(left/right);break;}}else{st.push(stoi(str));}}return st.top();}
};
用包装器后
class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> st;map<string, function<int(int, int)>> opFuncMap = {{"+", [](int a, int b){return a + b; }},{"-", [](int a, int b){return a - b; }},{"*", [](int a, int b){return a * b; }},{"/", [](int a, int b){return a / b; }}};//这里就是map的初始化,用C++11的列表初始化for(auto str : tokens){if(opFuncMap.count(str)){int right = st.top();st.pop();int left = st.top();st.pop();st.push(opFuncMap[str](left, right));}else{st.push(stoi(str));}}return st.top();}
};
包装器也可以包装成员函数。
class Plus
{
public:static int plus1(int a, int b){return a + b;}double plus2(double a, double b){return (a + b) * _rate;}
private:int _rate = 2;
};int main()
{
class Plus
{
public:Plus(int rate = 2):_rate(rate){}static int plus1(int a, int b){return a + b;}double plus2(double a, double b){return (a + b) * _rate;}
private:int _rate = 2;
};int main()
{function<int(int, int)> f1 = Plus::plus1;function<int(Plus, double, double)> f2 = &Plus::plus2;cout << f1(1, 2) << endl;cout << f2(Plus(), 20, 20) << endl;Plus p1(3);cout << f2(p1, 20, 20) << endl;return 0;
}
静态成员函数可以直接调用,而非静态的需要在第一个位置加上类名,因为有this指针,然后后面的Plus前加上&,静态函数也可以加上这个&,使用这个函数的时候,非静态需要在第一个参数位置放上类的对象,可以是匿名对象,如果在声明f2时,传的是*Plus,那么下面调用时就必须传对象的地址,所以就不能传匿名对象的地址,因为右值无法取地址。
包装器本质上是仿函数,f1,f2,f3就是对象,然后调用operator(),传过去参数,然后operator()再去调用对应函数,传类的对象就用对象来调用,传指针就指针来调用。
2、绑定
绑定是一个函数模板,用来调整参数。绑定是一个通用的函数适配器,接受一个可调用对象,可调用对象就是三个,函数指针、lambda、仿函数,生成一个新的可调用对象来适配。
bind函数第一个参数是一个万能引用,左右值都可传,然后后面的是占位符,_1表示第一个参数,_2表示第二个参数,以此类推,这些占位符是一个placeholders空间里。
int Print(int a, int b)
{cout << a << " ";cout << b << endl;
}int main()
{Print(10, 20);auto RP = bind(Print, placeholders::_2, placeholders::_1);RP(10, 20);//再次调用就换了顺序了。return 0;
}
如果bind写着_1在_2前面,那就没换顺序,要换顺序占位符就得对应着写。bind函数会返回一个对象,我们可以用auto来推演类型,还可以用function<void(int, int)>。实际调用的还是Print,不过适配器就是套了一个壳。
绑定真正有用的是改变参数个数
用这段代码做例子
class Sub
{
public:Sub(int rate):_rate(rate){}int func(int a, int b){return (a - b) * _rate;}
private:int _rate;
};class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> st;map<string, function<int(int, int)>> opFuncMap ={{"+", [](int a, int b) {return a + b; }},{"-", [](int a, int b) {return a - b; }},{"*", [](int a, int b) {return a * b; }},{"/", [](int a, int b) {return a / b; }}};//这里就是map的初始化,用C++11的列表初始化for (auto str : tokens){if (opFuncMap.count(str)){int right = st.top();st.pop();int left = st.top();st.pop();st.push(opFuncMap[str](left, right));}else{st.push(stoi(str));}}return st.top();}
};int main()
{function<int(Sub, int, int)> fSub = &Sub::func;fSub(Sub(1), 10, 20);return 0;
}
这是上面包装器的写法。这样的写法无法给opFuncMap传fSub对象,因为参数个数不一致,这时候就是绑定的作用体现了。
function<int(int, int)> fSub = bind(&Sub::func, Sub(1), placeholders::_1, placeholders::_2);fSub(10, 20);
把Sub(1)对象显式地传给func函数,顺序没有变,只是第一个参数显示传,剩下两个就从_1开始排顺序。也可以对其他参数来绑定。
function<int(int, int)> fSub = bind(&Sub::func, placeholders::_1, 10, placeholders::_2);fSub(Sub(1), 20);
本篇gitee
结束。
相关文章:
C++学习记录——이십팔 C++11(4)
文章目录 包装器1、functional2、绑定 这一篇比较简短,只是因为后要写异常和智能指针,所以就把它单独放在了一篇博客,后面新开几篇博客来写异常和智能指针 包装器 1、functional 包装器是一个类模板,对可调用对象类型进行再封装…...
UE学习记录03----UE5.2 使用拖拽生成模型
0.创建蓝图控件,自己想要展示的样子 1.侦测鼠标拖动 2.创建拖动操作 3.拖动结束时生成模型 3.1创建actor , 创建变量EntityMesh设为可编辑 生成Actor,创建变量EntityMesh设为可编辑 屏幕鼠标位置转化为3D场景位置 4.将texture设置为变量并设为可编辑&am…...
Spring Cache框架(缓存)
1、介绍: Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单加个注解,就能实现缓存功能。它提供了一层抽象,底层可以切换不同的cache实现。具体就是通过CacheManager 接口来实现不同的缓存技术。 针对不同…...
Linux学习之Ubuntu 20使用systemd管理OpenResty服务
sudo cat /etc/issue可以看到操作系统的版本是Ubuntu 20.04.4 LTS,sudo lsb_release -r可以看到版本是20.04,sudo uname -r可以看到内核版本是5.5.19,sudo make -v可以看到版本是GNU Make 4.2.1。 需要先参考我的博客《Linux学习之Ubuntu 2…...
[数据集][目标检测]疲劳驾驶数据集VOC格式4类别-4362张
数据集格式:Pascal VOC格式(不包含分割的txt文件,仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数):4362 标注数量(xml文件个数):4362 标注类别数:4 标注类别名称:["closed_eye","closed_mouth"…...
matlab使用教程(25)—常微分方程(ODE)选项
1.ODE 选项摘要 解算 ODE 经常要求微调参数、调整误差容限或向求解器传递附加信息。本主题说明如何指定选项以及每个选项与哪些微分方程求解器兼容。 1.1 选项语法 使用 odeset 函数创建 options 结构体,然后将其作为第四个输入参数传递给求解器。例如࿰…...
MybatisPlus简单到入门
一、MybatisPlus简介 1、入门案例(重点): 1.SpringBoot整合MP1).创建新模块选择,Spring项初始化。2).选择当前模块使用的技术,只保留MySQL Driver就行,不要选择mybatis避免与后面导入mybatisPlus的依赖发…...
9. 优化器
9.1 优化器 ① 损失函数调用backward方法,就可以调用损失函数的反向传播方法,就可以求出我们需要调节的梯度,我们就可以利用我们的优化器就可以根据梯度对参数进行调整,达到整体误差降低的目的。 ② 梯度要清零,如果梯…...
go学习之流程控制语句
文章目录 流程控制语句1.顺序控制2.分支控制2.1单分支2.2双分支单分支和双分支的四个题目switch分支结构 3.循环控制for循环控制while 和do...while的实现 4.跳转控制语句breakcontinuegotoreturngotoreturn 流程控制语句 介绍:在程序中,程序运行的流程…...
docker基于已有容器和通过Dockerfile进行制作镜像配置介绍
目录 一.制作镜像的两种方式 1.在已有容器中更新并提交这个镜像 2.使用Dockerfile来制作 二.基于容器制作镜像 1.格式 (1)主要格式 (2)可选参数 2.案例 基于容器创建镜像设置标签并进行验证是否可用 (1&…...
2022年09月 C/C++(四级)真题解析#中国电子学会#全国青少年软件编程等级考试
第1题:最长上升子序列 一个数的序列bi,当b1 < b2 < … < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, …, aN),我们可以得到一些上升的子序列(ai1, ai2, …, aiK),这里1 < i1 < i2 &…...
二级MySQL(九)——表格数据处理练习
在Mysql中,可以用INSERT或【REPLACE】语句,向数据库中已一个已有的表中插入一行或多行记录。 在Mysql中,可以用【DELETE】或【TRUNCATE】语句删除表中的所有记录。 在Mysql中,可以用【UPDATE】语句来修改数据表中的记录。 为了完…...
QT ListQvector at赋值出错以及解决办法 QT基础入门【QT存储结构】
1、问题 error: passing const QString as this argument discards qualifiers error: assignment of read-only location vec.QVector<int>::at(0) 在Qt中QList,Qvector一般获取元素都是通过at(index)来获取,但是at()的返回是一个const & 常引用,也就是元素不支…...
STM32 CubeMX (H750)RGB屏幕 LTDC
STM32 CubeMX STM32 RGB888 LTDC STM32 CubeMX一、STM32 CubeMX 设置时钟树LTDC使能设置屏幕参数修改RGB888的GPIO 二、代码部分效果 RGB屏幕线束定义: 一、STM32 CubeMX 设置 时钟树 这里设置的时钟,关于刷新速度 举例子:LCD_CLK24MHz 时…...
Redis问题集合(三)在Redis容器里设置键值对
前言 前提是已经拉取了Redis镜像并创建了对应的容器做个记录,方便后续查看 步骤 查看Redis容器的ID:docker ps -a 进入容器:docker exec -it 容器ID /bin/bash进入redis命令行:redis-cli输入密码:auth 配置密码 查看…...
spark中排查Premature EOF: no length prefix available
报错信息 /07/22 10:20:28 WARN DFSClient: Error Recovery for block BP-888461729-172.16.34.148-1397820377004:blk_15089246483_16183344527 in pipeline 172.16.34.64:50010, 172.16.34.223:50010: bad datanode 172.16.34.64:50010 [DataStreamer for file /bdp/data/u9…...
numpy高级函数之where和extract函数
1 numpy.where() 函数返回输入数组中满足给定条件的元素的索引 ---------------------------------------------------- 代码: n1np.random.randint(10,20,10) n2np.where(n1>15) 结果: [17 15 19 15 12 10 16 11 15 13] #原始数组 (array([…...
用Python写一个武侠游戏
前言 在本教程中,我们将使用Python写一个武侠类的游戏,大的框架全部搭好了,很多元素都可以自己添加,让游戏更丰富 📝个人主页→数据挖掘博主ZTLJQ的主页 个人推荐python学习系列: ☄️爬虫JS逆向系列专栏 -…...
Java --- 异常处理
目录 一、什么是异常 二、异常抛出机制 三、如何对待异常 四、 Java异常体系 4.1、Throwable 4.2、Error 4.2、Exception 4.2.1、编译时异常 4.2.2、运行时期异常 五、异常处理 5.1、捕获异常(try-catch) 5.1.2、catch中异常处理方式 …...
CDN/DCDN(全站加速)排查过程中如何获取Eagle ID/UUID
目录 前言1.通过浏览器直接访问文件时获取Request ID 前言 阿里云CDN/DCDN(全站加速)为接收到的每个请求分配唯一的服务器请求ID,作为关联各类日志信息的标识符。当您在使用CDN/DCDN(全站加速)过程中遇到错误且希望阿里云技术支持提供协助时,需要提交失…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
