C++可调用对象

C++11中有一个重要的概念,叫可调用对象,

可调用对象用途广泛,比如作为线程的执行对象,或者在使用一些基于范围的模版函数时( sort()、all_of()、find_if()),常常需要我们传入一个可调用对象,以指明我们需要对范围中的每个元素进行怎样的处理。

总的来说,可调用对象有以下几种,

  • 普通函数

  • 函数指针

  • 仿函数,即重载了operator()运算符的类对象

  • 匿名函数,即Lambda表达式

  • std::function

其中前面三种用法比较简单,放在一类中讲

普通函数、函数指针、仿函数

#include <iostream>
#include <thread>
#include <functional>
#include <algorithm>
#include <vector>//仿函数
struct functor{int operator()(const int &a, const int &b) const{return a < b;}
};
//普通函数
bool normal_func_cmp(const int &a, const int &b) {return a < b; // 从小到大排列
}//函数指针
typedef bool (*p_func)(const int &a, const int &b);
int main(int argc, const char * argv[]) {// insert code here...std::vector<int> v1 = {1, 5, 7, 4, 6, 2, 6};std::vector<int> v2 = v1;std::vector<int> v3 = v1;//使用普通函数排序sort(v1.begin(), v1.end(), normal_func_cmp);for(auto num : v1) {std::cout << num << ' ';}std::cout << std::endl;//使用仿函数排序sort(v2.begin(), v2.end(), functor());for(auto num : v2) {std::cout << num << ' ';}std::cout << std::endl;//使用函数指针排序p_func p = normal_func_cmp;sort(v3.begin(), v3.end(), p);for(auto num : v3) {std::cout << num << ' ';}return 0;
}

匿名函数 Lambda 表达式

定义

[captures] (params) mutable -> return_type { statments;}

  • [captures]为捕获列表,用于捕获外层变量。[&]表示捕获当前范围内所有局部变量。

    • [val]:表示以传值方式捕捉变量val

    • [=]:表示以传值方式捕捉当前作用域中的变量,包括this指针。

    • [&val]:表示以引用方式传递捕捉变量val。

    • [&]:表示以引用方式传递捕捉当前作用域中的所有变量,包括this指针。

    • [this]:表示以传值方式捕捉当前的this指针。

  • params:参数列表。与普通函数参数列表使用相同。如果不需要传递参数,可以连同()一起省略。

  • mutable : 默认情况下,lambda函数总是一个const函数,捕捉的传值参数具有常性,mutable可以取消常性。使用mutable修饰符时,参数列表不能省略,即使参数为空。

  • ->return_type : 返回值,如果没有返回类型,则可以省略这部分。想知道为什么返回类型可以这么表示,这涉及到c++11的另一特性,参见自动类型推导。

  • statments: {函数体}:在函数体内除了可以使用参数外,还能使用捕捉的变量。

举例

void lambda_test() {/* 最简单的lambda表达式 */[]{};//值传递int a = 1;int b = 2;auto add_lambda_func_val = [=] () mutable{ a = a + b;};add_lambda_func_val();//由于传递的是当前局部变量的拷贝,所以a不会被修改std::cout << a << " " << b << std::endl;//引用传递auto add_lambda_func_ref = [&] (){  a = a + b;};add_lambda_func_ref();//由于传递的是当前局部变量的引用,所以a被修改std::cout << a << " " << b << std::endl;//可以对单个变量进行捕捉auto add_lambda_func_ref2 = [&a,b] () mutable { a = a + b; b = a + b; };add_lambda_func_ref2();std::cout << a << " " << b << std::endl;
} 

std::function

std::function在C++11后加入标准,可以用它来描述C++中所有可调用实体,它是是可调用对象的包装器,声明如下:

普通声明

#include <functional>
// 声明一个返回值为int,参数为两个int的可调用对象类型
std::function<int(int, int)> Func;

其他函数实体转化为std::function

std::function 的强大之处在于,它能兼容所有callable实体

 //所有callable实体都能给function接收,这里以lambda为例auto lambda = [](int a, int b)->int {return a + b;};test_functionnal = lambda;
...
//成员函数和静态函数比较特殊
//成员函数需要传入对象指针
//std::placeholders::_1是占位符,代表需要接收一个参数,如果要接收多个,可以使用std::placeholders::_2、std::placeholders::_3...MyClass object;test_functionnal = std::bind(&MyClass::sum, &object, std::placeholders::_1, std::placeholders::_2);std::cout << "class member function : "<< test_functionnal(1, 2)<< std::endl;

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

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

相关文章

算法基础-位运算

>> &#xff08;右移运算&#xff09; x >> y&#xff1a;表示将x的二进制值右移y位。 正数是直接右移y位&#xff0c;则高位&#xff08;最左边&#xff09;补y个0。 负数是求补码&#xff0c;然后右移y位&#xff0c;最高位补y个1&#xff0c;再求反码&#xff…

Gamma基线估算

在使用Gamma软件处理DInSAR数据时&#xff0c;基线估算是一个非常关键的步骤。Gamma软件提供了一系列工具来计算和处理基线信息&#xff0c;以确保干涉图像的准确性和后续形变分析的精度。以下是Gamma软件中基线估算的详细步骤&#xff1a; 1. 初始化基线计算 (base_init) 首…

更适合编写股票盯盘软件或者量化交易平台的语言是Python还是C

炒股自动化&#xff1a;申请官方API接口&#xff0c;散户也可以 python炒股自动化&#xff08;0&#xff09;&#xff0c;申请券商API接口 python炒股自动化&#xff08;1&#xff09;&#xff0c;量化交易接口区别 Python炒股自动化&#xff08;2&#xff09;&#xff1a;获取…

集成电路学习:什么是DAC数模转换器

DAC&#xff1a;数模转换器 DAC&#xff0c;全称Digital-to-Analog Converter&#xff0c;即数模转换器&#xff0c;是一种电子设备或电路&#xff0c;用于将数字信号转换为相应的模拟信号。在现代电子系统中&#xff0c;DAC扮演着至关重要的角色&#xff0c;它实现了数字电路与…

如何在UE5.4中重新定位动画?

动画在游戏和电影制作中扮演着至关重要的角色&#xff0c;而在虚幻引擎5.4&#xff08;UE5.4&#xff09;这一强大的实时3D创作平台中&#xff0c;重新定位动画的能力更是将创意表达推向了新的高度。本文将引导您探索UE5.4中重新定位动画的技巧&#xff0c;确保您的动画作品不仅…

Unity | 基础知识

装箱和拆箱&#xff1a; 获取对方的类型&#xff1a; GetType通过打点调用 as进行类型转换 运用Convert进行类型转换&#xff1a; 二维数组的定义 结构体类型 不同名称空间来调用&#xff1a;

Auto-Unit-Test-Case-Generator -- java项目自动测试生成

0.Pre-预备知识&#xff1a; 0.1.Maven是什么&#xff1f; [by Maven是什么&#xff1f;有什么作用&#xff1f;Maven的核心内容简述_maven是干什么用-CSDN博客 ] 是Java 领域中最流行的自动化构建工具之一&#xff0c;Maven 作为 Java 项目管理工具&#xff0c;具有: 包管…

互联网全景消息(1)之RabbitMq基础入门

一、消息中间件 1.1消息队列回顾 消息队列中间件是分布式系统中重要的组件&#xff0c;主要解决应用解耦&#xff0c;异步消息&#xff0c;流量削锋等问题&#xff0c;实 现高性能&#xff0c;高可用&#xff0c;可伸缩和最终一致性架构。目前使用较多的消息队列有ActiveMQ &a…

数据库mysql8.x中修改密码的方法

mysql数据库最新版本9.x都出来了&#xff0c;再不学就要被淘汰了&#xff01;&#xff01;这次使用的是8.0.39版本&#xff0c;大家可以去官网下载使用。 官网地址:https://dev.mysql.com/downloads/mysql/ 安装好后&#xff0c;默认密码是一串很难记忆的字符&#xff0c;记录…

day-46 旋转图像

思路 不能使用辅助数组&#xff0c;所以关键在于弄清楚旋转后坐标的变化规律。当矩阵的大小n为偶数时&#xff0c;以n/2行和n/2列的元素为起点&#xff0c;当矩阵的大小n为奇数时&#xff0c;以n/2行和&#xff08;n1&#xff09;/2列的元素为起点 解题过程 关键&#xff1a;旋…

【JavaWeb】Cookie、Session

文章目录 Cookie、Session一、Cookie&#xff08;客户端&#xff09;1、Cookie 的 特点2、Cookie 的 工作原理3、Cookie 的 基本操作5、Cookie 的 域名与路径6、Cookie 的 存活时间7、Cookie 的 删除 二、Session&#xff08;服务端&#xff09;1、Session 的 特点2、Session 的…

Python进阶————面向对象高级

面向对象高级 前言一、继承1.1. 单继承1.2. 多继承1.3. 方法重写1.4. 子类调用父类方法1.4.1 父类名.父类方法名()1.4.2 super().父类方法名() 1.5. 多层继承 二、封装2.1. 私有属性2.2. 私有方法 三、多态3.1. 多态的条件3.2. 多态的定义 四、面向对象的其他特性4.1. 对象属性…

【学习笔记】卫星通信NTN 3GPP标准化进展分析(四)- 3GPP Release18内容

一、引言&#xff1a; 本文来自3GPP Joern Krause, 3GPP MCC (May 14,2024) Non-Terrestrial Networks (NTN) (3gpp.org) 本文总结了NTN标准化进程以及后续的研究计划&#xff0c;是学习NTN协议的入门。 【学习笔记】卫星通信NTN 3GPP标准化进展分析&#xff08;一&#xff…

Codeforces Round 964 (Div. 4) A-E Java题解

比赛地址 Dashboard - Codeforces Round 964 (Div. 4) - Codeforces A题 签到题 给一个两位数 求各位上的数字和 直接对10取余加上本来的数除以10 // 注意类名必须为 Main, 不要有任何 package xxx 信息 // package Dduo; import java.io.*; import java.math.*; import j…

FFmpeg源码:av_rescale_rnd、av_rescale_q_rnd、av_rescale_q、av_add_stable函数分析

一、av_rescale_rnd函数 &#xff08;一&#xff09;av_rescale_rnd函数的声明 av_rescale_rnd函数声明在FFmpeg源码&#xff08;本文演示用的FFmpeg源码版本为7.0.1&#xff09;的头文件libavutil/mathematics.h中&#xff1a; /*** Rounding methods.*/ enum AVRounding {…

【Android自定义控件】Kotlin实现滚动效果的数字加减控件

前言 因业务上的需要&#xff0c;在APP中点餐时要有商品数目增减操作&#xff0c;数目增减的过程中有翻动的动画效果展现。在Android中有多种方式可以实现&#xff0c;本篇文章记录通过自定义View结合控件的平移动画相结合来实现此需求。 需求分析 根据上图分析控件的实现过程以…

力扣763-划分字母区间(Java详细题解)

题目链接&#xff1a;763. 划分字母区间 - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 因为本人最近都来刷贪心类的题目所以该题就默认用贪心方法来做。 贪心方法&#xff1a;局部最优推出全局最优。 如果一个题你觉得可以用局部最优推出全局最优&#xf…

如何在 Vim 中显示行号

前言 Vim 是一款功能强大的文本编辑器&#xff0c;在 Linux、Mac 和 Windows 上都有广泛的应用。对于开发人员来说&#xff0c;能够快速查看代码行号是一个非常实用的功能&#xff0c;尤其是在进行调试或阅读长文件时。本文将介绍如何在 Vim 中开启和关闭行号显示。 开启行号…

【STM32】RS485

RS485是常见的串口接口。 大部分图片来源&#xff1a;正点原子HAL库课程 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 目录 1 串口、UART、TTL、RS232、RS422、RS485的关系 1.1 串口 1.2 UART、TTL、RS232、RS422、RS485 1.3 常见串口标准的比较 …

JS 如何判断是否是IE浏览器

例子 if(!!window.ActiveXObject || "ActiveXObject" in window){alert("抱歉&#xff0c;不支持IE浏览器&#xff01;");return; }