当前位置: 首页 > news >正文

[C++] C++ 11的functional模块介绍和使用案例

functional模块介绍

functional模块是C++ 11提供了一组函数对象和算法,用于增强C++的函数式编程能力。该模块中的函数对象和算法可以大大简化代码,并提供了一些有用的工具,例如函数适配器和函数对象的组合。

functional模块中的函数对象包括:

  1. plus:加法函数对象,用于将两个参数相加。
  2. minus:减法函数对象,用于将第一个参数减去第二个参数。
  3. multiplies:乘法函数对象,用于将两个参数相乘。
  4. divides:除法函数对象,用于将第一个参数除以第二个参数。
  5. modulus:取模函数对象,用于返回第一个参数除以第二个参数的余数。
  6. negate:取反函数对象,将参数取反。

functional模块中的算法包括:

  1. bind:将一个函数对象和一些参数绑定在一起,生成一个新的函数对象。
  2. mem_fn:将一个成员函数包装成函数对象。
  3. not1:对一个函数对象进行逻辑非运算。
  4. ref:将一个对象包装成一个引用包装器。
  5. cref:将一个对象包装成一个const引用包装器。

使用案例

案例一

#include <iostream>
#include <functional>int main() {std::plus<int> plusFunc;int result = plusFunc(1, 2);  // 将1和2相加,返回3std::cout << result << std::endl;return 0;
}

在上面的例子中,我们创建了一个std::plus<int>的实例plusFunc,该实例可以用于将两个整数相加。然后,我们调用plusFunc函数对象,传入参数1和2,并将返回的结果赋值给result变量。最后,我们将结果输出到控制台,得到的输出结果是3。

使用std::plus函数对象的好处是,它可以与其他函数对象和算法结合使用,例如使用std::transform算法对一个容器中的元素进行相加操作:

#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>int main() {std::vector<int> nums {1, 2, 3, 4, 5};std::vector<int> result(nums.size());std::transform(nums.begin(), nums.end(), nums.begin(), std::negate<int>());std::transform(nums.begin(), nums.end(), result.begin(), std::bind(std::plus<int>(), std::placeholders::_1, 2));for (int num : result) {std::cout << num << " ";}return 0;
}

在上面的例子中,我们首先使用std::transform算法和std::negate函数对象对nums容器中的元素进行取反操作。然后,使用std::transform算法和std::bind函数将nums中的每个元素与2相加,并将结果存储在result容器中。最后,我们遍历result容器并输出每个元素的值。输出结果为-1 0 1 2 3,表示nums中的每个元素都加上了2。

这个例子展示了std::plus函数对象的灵活性,它可以与其他函数对象和算法结合使用,简化了代码,并提供了更好的可读性和可维护性。

案例二

#include <iostream>
#include <functional>int add(int a, int b) {return a + b;
}int subtract(int a, int b) {return a - b;
}int main() {std::function<int(int, int)> func1 = add;std::function<int(int, int)> func2 = std::bind(subtract, std::placeholders::_2, std::placeholders::_1);int result1 = func1(1, 2);  // 调用add函数,返回3int result2 = func2(2, 1);  // 调用subtract函数,返回1std::cout << result1 << std::endl;std::cout << result2 << std::endl;return 0;
}

在上面的例子中,我们定义了两个函数add和subtract,并使用std::function将它们包装成函数对象func1和func2。然后,我们可以像调用普通函数一样使用这些函数对象,通过调用func1和func2来执行对应的函数。输出结果分别为3和1。

在这个例子中,我们使用了bind函数将subtract函数的两个参数绑定在一起,然后通过调整参数的顺序来实现减法运算。这是functional模块中的一个常见用法,可以用来生成新的函数对象。

案例三

#include <iostream>
#include <functional>class MyClass {
public:void printMessage(const std::string& message) {std::cout << message << std::endl;}
};int main() {MyClass obj;auto printFunc = std::mem_fn(&MyClass::printMessage);printFunc(obj, "Hello, world!");  // 调用obj对象的printMessage函数,并传入参数"Hello, world!"return 0;
}

在上面的例子中,我们定义了一个名为MyClass的类,该类具有一个成员函数printMessage,用于输出一条消息。然后,我们创建了一个MyClass类型的对象obj,并使用std::mem_fn将printMessage函数转化为一个函数对象printFunc。最后,我们调用printFunc函数对象,传入obj对象和字符串参数"Hello, world!",从而调用了obj对象的printMessage函数并输出了消息。

使用std::mem_fn函数对象的好处是,它允许我们以通用的方式处理成员函数指针和成员函数对象,可以与其他函数对象和算法结合使用。例如,我们可以通过std::transform算法将一个容器中的每个元素调用成员函数并获取结果:

#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>class MyClass {
public:int multiply(int x, int y) {return x * y;}
};int main() {std::vector<int> nums {1, 2, 3, 4, 5};std::vector<int> result(nums.size());MyClass obj;auto multiplyFunc = std::mem_fn(&MyClass::multiply);std::transform(nums.begin(), nums.end(), result.begin(), std::bind(multiplyFunc, &obj, std::placeholders::_1, 2));for (int num : result) {std::cout << num << " ";}return 0;
}

在上面的例子中,我们定义了一个名为MyClass的类,该类具有一个成员函数multiply,用于计算两个整数的乘积。然后,我们创建了一个MyClass类型的对象obj,并使用std::mem_fn将multiply函数转化为一个函数对象multiplyFunc。最后,我们使用std::transform算法和std::bind函数将nums容器中的每个元素和数字2传入multiplyFunc函数对象中进行计算,并将结果存储在result容器中。最后,我们遍历result容器并输出每个元素的值。输出结果为2 4 6 8 10,表示nums中的每个元素都乘以了2。

这个例子展示了std::mem_fn函数对象的灵活性,它允许我们处理成员函数指针和成员函数对象,并与其他函数对象和算法结合使用,简化了代码,并提供了更好的可读性和可维护性。

案例四

#include <iostream>
#include <functional>void updateValue(int& value) {value += 10;
}int main() {int num = 5;std::cout << "Before update: " << num << std::endl;std::function<void()> updateFunc = std::bind(updateValue, std::ref(num));updateFunc();std::cout << "After update: " << num << std::endl;return 0;
}

在上面的例子中,我们定义了一个名为updateValue的函数,该函数接受一个引用参数,并将其值增加10。然后,我们创建了一个名为num的整数变量,初始值为5。接下来,我们使用std::ref函数模板将num对象转化为一个引用包装器,并通过std::bind函数将updateValue函数与引用包装器绑定到一起,创建一个函数对象updateFunc。最后,我们调用updateFunc函数对象,从而实际调用了updateValue函数,并传递了num对象的引用作为参数。输出结果为:

Before update: 5
After update: 15

可以看到,通过使用std::ref函数模板,我们可以在函数调用中传递对象的引用,从而实现对对象的修改。

案例五

#include <iostream>
#include <functional>void printValue(const int& value) {std::cout << "Value: " << value << std::endl;
}int main() {int num = 10;std::function<void()> printFunc = std::bind(printValue, std::cref(num));printFunc();return 0;
}

在上面的例子中,我们定义了一个名为printValue的函数,该函数接受一个常量引用参数,并打印该值。然后,我们创建了一个名为num的整数变量,初始值为10。接下来,我们使用std::cref函数模板将num对象转化为一个常量引用包装器,并通过std::bind函数将printValue函数与常量引用包装器绑定到一起,创建一个函数对象printFunc。最后,我们调用printFunc函数对象,从而实际调用了printValue函数,并传递了num对象的常量引用作为参数。输出结果为:

Value: 10

可以看到,通过使用std::cref函数模板,我们可以在函数调用中传递对象的常量引用,从而实现对对象的只读访问。

案例六

#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>bool isOdd(int num) {return num % 2 != 0;
}int main() {std::vector<int> nums {1, 2, 3, 4, 5};std::vector<int> evenNums;std::copy_if(nums.begin(), nums.end(), std::back_inserter(evenNums), std::not1(std::ptr_fun(isOdd)));for (int num : evenNums) {std::cout << num << " ";}std::cout << std::endl;return 0;
}

在上面的例子中,我们定义了一个名为isOdd的谓词函数,该函数接受一个整数参数,并判断该整数是否为奇数。然后,我们创建了一个整数类型的vector容器nums,并使用std::copy_if算法和std::not1函数模板将nums容器中的所有偶数元素复制到另一个vector容器evenNums中。在调用std::copy_if算法时,我们使用std::not1函数模板将isOdd谓词函数进行否定操作,从而实现对偶数元素的筛选。最后,我们遍历evenNums容器并输出其中的所有元素。输出结果为:

2 4

这个例子展示了std::not1函数模板的用途,可以对谓词函数进行否定操作,从而实现相反的逻辑判断。在实际开发中,std::not1函数模板可以用于各种需要对谓词函数进行逻辑反操作的场景,例如在STL算法中对元素进行筛选、排序或处理等操作。

相关文章:

[C++] C++ 11的functional模块介绍和使用案例

functional模块介绍 functional模块是C 11提供了一组函数对象和算法&#xff0c;用于增强C的函数式编程能力。该模块中的函数对象和算法可以大大简化代码&#xff0c;并提供了一些有用的工具&#xff0c;例如函数适配器和函数对象的组合。 functional模块中的函数对象包括&am…...

kubernetes基本概念和操作

基本概念和操作 1.Namespace1.1概述1.2应用示例 2.Pod2.1概述2.2语法及应用示例 3.Label3.1概述3.2语法及应用示例 4.Deployment4.1概述4.2语法及应用示例 5.Service5.1概述5.2语法及应用示例5.2.1创建集群内部可访问的Service5.2.2创建集群外部可访问的Service5.2.3删除服务5.…...

20240128周报-网络太杂,Tomcat太难

今天来做个小总结吧&#xff0c;之前说想用几个月的时间将Java生态给整理一遍&#xff0c;该工作已经进入第三周了。先和各位老老板汇报一下上一周的工作&#xff0c;然后说一下本周的计划和后面的计划。 1.上周工作 上周的计划是将网络和Tomcat的内容梳理一番&#xff0c;但…...

DES加密原理

DES加密算法综合运用了置换、代替、代数等多种密码技术&#xff0c;具有设计精 巧、实现容易、使用方便等特点。DES加密算法的明文、密文和密钥的分组长度 都是64位&#xff0c;详细的DES加密算法结构如图6-10所示。 图6-10 DES加密算法结构图 DES加密过程如下所示&#xff…...

react 之 useCallback

简单讲述下useCallback的使用方法&#xff0c;useCallback也是用来缓存的&#xff0c;只不过是用于做函数缓存 // useCallbackimport { memo, useCallback, useState } from "react"const Input memo(function Input ({ onChange }) {console.log(子组件重新渲染了…...

OfficeWeb365 Readfile 任意文件读取漏洞复现

0x01 产品简介 OfficeWeb365 是专注于 Office 文档在线预览及PDF文档在线预览云服务,包括 Microsoft Word 文档在线预览、Excel 表格在线预览、Powerpoint 演示文档在线预览,WPS 文字处理、WPS 表格、WPS 演示及 Adobe PDF 文档在线预览。 0x02 漏洞概述 OfficeWeb365 Rea…...

UnityShader(十三)Unity内置的函数

在计算光照模型时我们需要得到许多数据&#xff0c;比如光源方向、视角方向这种基本信息。 在之前的例子中都是自行在代码里计算的&#xff0c;比如&#xff1a; normalize(_WorldSpaceLight0Pos.xyz) 得到光源方向&#xff08;这种方法实际只适用平行光&#xff09; normaliz…...

【开源】基于Qt5的ROS1/ROS2人机交互软件(支持地图编辑/多点导航)

本项目基于Qt5开发&#xff0c;基于CMake进行构建&#xff0c;可以实现一套代码同时在ROS1/ROS2系统中使用(本项目已接入CI,保证多ROS版本/系统版本可用性) 项目地址&#xff1a; https://github.com/chengyangkj/Ros_Qt5_Gui_App 软件在编译时会自动识别环境变量中的ROS1/ROS…...

Spring和SpringBoot的区别是什么

Spring 和 Spring Boot 是 Java 开发领域内两个极其重要且紧密相关的框架&#xff0c;它们各自在企业级应用开发中扮演着不同的角色&#xff0c;并带来了一系列革新性的变化。以下是关于两者之间主要区别的详细分析&#xff1a; 一、设计理念与定位 Spring Framework Spring 是…...

布局技巧及CSS初始化

一&#xff0c;margin负值巧妙应用 二&#xff0c;文字围绕浮动元素 三&#xff0c;行内块 四&#xff0c;CSS三角强化 五&#xff0c;CSS初始化 一&#xff0c;margin负值巧妙应用 制作盒子的细线边框&#xff1a; 鼠标经过li后变色&#xff1a; 二&#xff0c;文字围绕…...

excel怎么设置密码?轻松保护您的工作表

在数字化时代&#xff0c;数据的安全性显得尤为重要。excel作为我们日常工作中广泛使用的办公软件&#xff0c;其中可能包含了大量的敏感数据。为了确保这些数据不被未授权的人访问&#xff0c;本文将为您详细介绍excel怎么设置密码&#xff0c;从而有效地保护您的数据安全。 方…...

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之TimePicker组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之TimePicker组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、TimePicker组件 TextClock组件通过文本将当前系统时间显示在设备上。支持不…...

Springboot集成Camunda并完成一条流程实例

&#x1f496;专栏简介 ✔️本专栏将从Camunda(卡蒙达) 7中的关键概念到实现中国式工作流相关功能。 ✔️文章中只包含演示核心代码及测试数据&#xff0c;完整代码可查看作者的开源项目snail-camunda ✔️请给snail-camunda 点颗星吧&#x1f618; &#x1f496;设计流程定…...

宠物用品/宠物自动饮水机方案

宠物自动饮水机方案原理 宠物自动饮水机&#xff0c;也叫做智能宠物饮水机&#xff0c;是一种为宠物设计的智能化饮水器。应用核心主要在于智能化水泵控制&#xff0c;以及外围传感器电路。 宠物自动饮水机使用方便&#xff0c;不用频繁的换水。另外&#xff0c;自来水的水质可…...

git小白进阶之路

git是最常用的版本控制工具&#xff0c;我对其进行了整理后续补充&#xff0c;这个文档欢迎大家来讨论&#xff0c;当前我的视频梳理&#xff1a; git小白进阶之路_哔哩哔哩_bilibili&#xff0c;非常希望大佬们能够批评指正&#xff0c;并多多交流。 目录 初始配置 配置账号…...

哈希表——C++

目录 一、首先使用拉链法&#xff1a; 二、开放寻址法 三、字符串哈希 1.具体如何使用进制的方式来存储字符前缀的可以看这个y总的这个图 2.接下来说一说算某个中间的区间的字符串哈希值 哈希表是一种数组之间互相映射的数据结构&#xff0c;比如举个简单的例子一个十个的数…...

LabVIEW叶片厚度远程监控

LabVIEW叶片厚度远程监控 随着网络技术的高速发展&#xff0c;远程监控广泛应用在各个领域。本文介绍了一种基于LabVIEW的植物叶片厚度远程监控系统&#xff0c;旨在实现对植物生长状况的精准监测和分析。 该系统利用LabVIEW软件开发工具&#xff0c;通过TCP网络协议实现数据…...

el-table动态合并

废话就不多说了&#xff0c;直接上代码&#xff01;&#xff01;&#xff01; 合并行 // 方法一 <template><div class"container"><el-table :data"dataSource" :border"true":header-cell-style"{ font-weight: normal,…...

【DevOps】产品需求文档(PRD)与常见原型软件

文章目录 1、PRD介绍1.1、概述1.2、前提条件1.3、主要目的1.4、关键内容1.5、表述方式1.6、需求评审人员1.7、一般内容结构 2、需求流程3、常见原型软件3.1、Word3.2、Axure3.2.1、详细介绍3.2.2、应用分类3.2.3、优缺点 3.3、摹客RP3.4、蓝湖3.5、GUI Design Studio 1、PRD介绍…...

【QT+QGIS跨平台编译】之十八:【Expat+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、Expat介绍二、文件下载三、文件分析四、pro文件五、编译实践一、Expat介绍 Expat库最初由James Clark创建,已经成为许多编程语言中常用的XML解析工具。它以其简单、快速和可靠的特点而受到广泛的认可和使用。 Expat库的优点包括: 快速:Expat的解析速度非常快…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...