C++11中的std::function

2023-11-07

文章转载自:http://www.jellythink.com/archives/771

看看这段代码

先来看看下面这两行代码:

std::function<void(EventKeyboard::KeyCode, Event*)> onKeyPressed;
std::function<void(EventKeyboard::KeyCode, Event*)> onKeyReleased;

这两行代码是从Cocos2d-x中摘出来的,重点是这两行代码的定义啊。std::function这是什么东西?如果你对上述两行代码表示毫无压力,那就不妨再看看本文,就当温故而知新吧。

 

std::function介绍

类模版std::function是一种通用、多态的函数封装。std::function的实例可以对任何可以调用的目标实体进行存储、复制、和调用操作,这些目标实体包括普通函数、Lambda表达式、函数指针、以及其它函数对象等。std::function对象是对C++中现有的可调用实体的一种类型安全的包裹(我们知道像函数指针这类可调用实体,是类型不安全的)。

通常std::function是一个函数对象类,它包装其它任意的函数对象,被包装的函数对象具有类型为T1, …,TN的N个参数,并且返回一个可转换到R类型的值。std::function使用 模板转换构造函数接收被包装的函数对象;特别是,闭包类型可以隐式地转换为std::function

最简单的理解就是:

通过std::function对C++中各种可调用实体(普通函数、Lambda表达式、函数指针、以及其它函数对象等)的封装,形成一个新的可调用的std::function对象;让我们不再纠结那么多的可调用实体。一切变的简单粗暴。

 

怎么使用std::function

使用std::function的感觉就是“万众归一”,下面就通过实际的代码例子,看看究竟怎么使用std::function。会使用了才是王道。

#include <functional>
#include <iostream>
using namespace std;

std::function< int(int)> Functional;

// 普通函数
int TestFunc(int a)
{
    return a;
}

// Lambda表达式
auto lambda = [](int a)->int{ return a; };

// 仿函数(functor)
class Functor
{
public:
    int operator()(int a)
    {
        return a;
    }
};

// 1.类成员函数
// 2.类静态函数
class TestClass
{
public:
    int ClassMember(int a) { return a; }
    static int StaticMember(int a) { return a; }
};

int main()
{
    // 普通函数
    Functional = TestFunc;
    int result = Functional(10);
    cout << "普通函数:"<< result << endl;

    // Lambda表达式
    Functional = lambda;
    result = Functional(20);
    cout << "Lambda表达式:"<< result << endl;

    // 仿函数
    Functor testFunctor;
    Functional = testFunctor;
    result = Functional(30);
    cout << "仿函数:"<< result << endl;

    // 类成员函数
    TestClass testObj;
    Functional = std::bind(&TestClass::ClassMember, testObj, std::placeholders::_1);
    result = Functional(40);
    cout << "类成员函数:"<< result << endl;

    // 类静态函数
    Functional = TestClass::StaticMember;
    result = Functional(50);
    cout << "类静态函数:"<< result << endl;

    return 0;
}

对于各个可调用实体转换成std::function类型的对象,上面的代码都有,运行一下代码,阅读一下上面那段简单的代码。总结了简单的用法以后,来看看一些需要注意的事项:

  • 关于可调用实体转换为std::function对象需要遵守以下两条原则:
    • 转换后的std::function对象的参数能转换为可调用实体的参数;
    • 可调用实体的返回值能转换为std::function对象的返回值。
  • std::function对象最大的用处就是在实现函数回调,使用者需要注意,它不能被用来检查相等或者不相等,但是可以与NULL或者nullptr进行比较。

 

为什么要用std::function

好用并实用的东西才会加入标准的。因为好用,实用,我们才在项目中使用它。std::function实现了一套类型消除机制,可以统一处理不同的函数对象类型。以前我们使用函数指针来完成这些;现在我们可以使用更安全的std::function来完成这些任务。

还有为什么?我也不知道还有为什么?等以后发现了更好的实际应用实例再回来说为什么吧。

总结

C++11的加入,貌似让C++变了一个语言似的,也有了Lambda表达式,好多东西都要去学习,好多新的语言特性。哦,慢慢来吧。

2014年12月5日 于深圳。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++11中的std::function 的相关文章

  • CLR 2.0 与 4.0 性能比较?

    如果在 CLR 4 0 下运行 为 CLR 2 0 编译的 NET 程序会运行得更快吗 应用程序配置
  • 如何从 C# 中的 dataTable.Select( ) 查询中删除单引号?

    所以我有一个经销商名称列表 我正在我的数据表中搜索它们 问题是 一些傻瓜必须被命名为 Young s 这会导致错误 drs dtDealers Select DealerName dealerName 所以我尝试替换字符串 尽管它对我不起作
  • 适合初学者的良好调试器教程[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有谁知道一个好的初学者教程 在 C 中使用调试器 我感觉自己好像错过了很多 我知道怎么做 单步执行代码并查看局部变量 虽然这常常给我带来问
  • 如何使用 Castle Windsor 将对象注入到 WCF IErrorHandler 实现中?

    我正在使用 WCF 开发一组服务 该应用程序正在使用 Castle Windsor 进行依赖注入 我添加了一个IErrorHandler通过属性添加到服务的实现 到目前为止一切正常 这IErrorHandler对象 一个名为FaultHan
  • 函数参数的默认参数是否被视为该参数的初始值设定项?

    假设我有这样的函数声明 static const int R 0 static const int I 0 void f const int r R void g int i I 根据 dcl fct default 1 如果在参数声明中指
  • unordered_map 中字符串的 C++ 哈希函数

    看起来 C 标准库中没有字符串的哈希函数 这是真的 在任何 c 编译器上使用字符串作为 unordered map 中的键的工作示例是什么 C STL提供模板专业化 http en cppreference com w cpp string
  • 在Linux中,找不到框架“.NETFramework,Version=v4.5”的参考程序集

    我已经设置了 Visual studio 来在我的 Ubuntu 机器上编译 C 代码 我将工作区 我的代码加载到 VS 我可以看到以下错误 The reference assemblies for framework NETFramewo
  • 告诉 Nancy 将枚举序列化为字符串

    Nancy 默认情况下在生成 JSON 响应时将枚举序列化为整数 我需要将枚举序列化为字符串 有一种方法可以通过创建来自定义 Nancy 的 JSON 序列化JavaScript 原始转换器 https github com NancyFx
  • 类型约束

    我有以下类层次结构 class Header IEnumerable
  • 打破 ReadFile() 阻塞 - 命名管道 (Windows API)

    为了简化 这是一种命名管道服务器正在等待命名管道客户端写入管道的情况 使用 WriteFile 阻塞的 Windows API 是 ReadFile 服务器已创建启用阻塞的同步管道 无重叠 I O 客户端已连接 现在服务器正在等待一些数据
  • IQueryable 单元或集成测试

    我有一个 Web api 并且公开了一个端点 如下所示 api 假期 name name 这是 Web api 的控制器 get 方法 public IQueryable
  • 如何在 C 中安全地声明 16 位字符串文字?

    我知道已经有一个标准方法 前缀为L wchar t test literal L Test 问题是wchar t不保证是16位 但是对于我的项目 我需要16位wchar t 我还想避免通过的要求 fshort wchar 那么 C 不是 C
  • 保护 APK 中的字符串

    我正在使用 Xamarin 的 Mono for Android 开发一个 Android 应用程序 我目前正在努力使用 Google Play API 添加应用内购买功能 为此 我需要从我的应用程序内向 Google 发送公共许可证密钥
  • 高效列出目录中的所有子目录

    请参阅迄今为止所采取的建议的编辑 我正在尝试使用 WinAPI 和 C 列出给定目录中的所有目录 文件夹 现在我的算法又慢又低效 使用 FindFirstFileEx 打开我正在搜索的文件夹 然后我查看目录中的每个文件 使用 FindNex
  • String.Empty 与 "" [重复]

    这个问题在这里已经有答案了 可能的重复 String Empty 和 有什么区别 https stackoverflow com questions 151472 what is the difference between string
  • 将数组作为参数传递

    如果我们修改作为方法内参数传递的数组的内容 则修改是在参数的副本而不是原始参数上完成的 因此结果不可见 当我们调用具有引用类型参数的方法时 会发生什么过程 这是我想问的代码示例 using System namespace Value Re
  • GCC 的“-Wl,option”和“-Xlinker option”语法之间有区别吗?

    我一直在查看一些配置文件 并且看到它们都被使用 尽管在不同的体系结构上 如果您在 Linux 机器上使用 GCC 将选项传递给链接器的两种语法之间有区别吗 据我所知 阅读 GCC 手册时 他们的解释几乎相同 From man gcc Xli
  • Objective-C / C 给出枚举默认值

    我在某处读到过关于给枚举默认值的内容 如下所示 typedef enum MarketNavigationTypeNone 0 MarketNavigationTypeHeirachy 1 MarketNavigationTypeMarke
  • 灵气序列解析问题

    我在使用 Spirit Qi 2 4 编写解析器时遇到一些问题 我有一系列键值对以以下格式解析
  • OpenCV SIFT 描述符关键点半径

    我正在深入研究OpenCV的SIFT描述符提取的实现 https github com Itseez opencv blob master modules nonfree src sift cpp 我发现了一些令人费解的代码来获取兴趣点邻域

随机推荐

  • CSDN周赛56期 - 八阿哥依旧

    之前54期被判作弊 申述无果 反被客服拉黑 水平不够 脾气够够的 让我彻底死心 从此粉转路 各种平台也不止C站一家 确实没有必要一棵树上吊shi 各位如果真心想通过竞赛提高自己的话 实在没必要来C站 整个娱人愚己 我这么说可不是恼羞成怒 看
  • 快速搜索Wox工具之Everything Client没有运行报错,解决办法!

    一直在用的一款快速搜索神器 Wox 但是在使用过程中出现一个报错 报错如下 Everything Client 没有运行 令我很烦 百度了一下 试了很多方法 还是不能发挥它的最大功效 由于我是一个好学的人 一直追踪这个问题 并寻求解决 终于
  • QT---QMainWindow初始化顺序

    C 构造 先子类以及成员 再父类以及成员 析构的顺序就是构造顺序的逆序 就是先析构父类 再析构子类 先析构本类 再析构本类的成员 QT 1 控件类 gt 控件提升类 gt QMainWindow类 2 子窗体的构造函数中初始化了父窗体的pa
  • 【log4j】

    文章目录 log4j 简介 组成 日志级别 log4j使用 占位符 log4j web 简介 Log4J 是 Apache 的一个开源项目 官网 http jakarta apache org log4j 通过在项目中使用 Log4J 我们
  • DC-UNet:重新思考UNet架构和双通道高效CNN医学图像

    摘要 经典UNet的体系架构在某些方面存在着局限性 因此本文对其结构提出了改进 1 设计高效的CNN架构来取代编码器和解码器 2 在最先进的U Net模型的基础上 应用残差模块来取代编码器和解码器之间的跳过连接来进行改进 医学图像分割是通过
  • eclipse编译慢 提高eclipse的性能

    编译慢原因有多种 其中可以通过修改eclipse ini文件设置缓存大小 并将工作空间的validation的多项验证去除 因为这些验证也为在编译时被执行 只保留几个必须的 我就只设置了xml验证 关闭checking for update
  • Spring Boot —Cache使用

    1 Spring缓存抽象 Spring从3 1开始定义了org springframework cache Cache和org springframework cache CacheManager接口来统一不同的缓存技术 并支持使用JCac
  • emcas利用矩形编辑在每行添加序列数字

    参考文章 http xahlee info emacs emacs emacs string rectangle ascii art html 通过阅读文章利用rectangle number lines函数实现 通过 查询文档发现 其绑定
  • matlab2016a贝叶斯工具箱,【Matlab】贝叶斯网络工具箱简介

    本文主要参考 以及自己对该工具箱的一点认识 通过借助该工具箱中的一个测试函数 k2demo1 m 了解整个贝叶斯网络工具箱的使用 1 给定一个贝叶斯网络结构 N 4 节点个数 即参数的个数 dag zeros N N C 1 S 2 R 3
  • 怎样使用vs2019 开始自己的第一个C++程序

    怎样使用vs2019 开始自己的第一个C 程序 一 新建项目 1 点击菜单栏 gt 文件 gt 新建 gt 项目 1 我们可以看到上方存在的语言 平台和项目类型的选项 语言这里我们就选择C 如果有需要可以选择所有语言 2 平台我们就选择wi
  • 07-----git add . 失败(warning: You ran ‘git add‘ with neither ‘-A (--all)‘ or ‘--ignore-removal‘)

    1 分析原因并解决 出错原因 远程仓库修改或者删除文件 而没有在本地更新 解决 git status 查看对应状态 git add A 或者 git add all 解决问题
  • linux 分区 dev,linux-kernel – 是/ dev / dm-1分区还是整个块设备?

    每个分区都是一个 整体 的块设备 您可以对任何分区进行子分区 然后再次对其进行子分区 然后再次 在您的示例中 dm 1可以映射到任何东西 原始设备 dmcrypt设备抽象 MD RAID支持的多路径 dm加密卷组上的逻辑卷 当设备初始化时
  • 浅浅写一下PPOCRLabel的使用及体验

    依赖包 我是基于之前建立好的paddle env环境 因此在使用过程中实际上 根据报错 需要的包只有这两个 pip install xlrd pip install PyQt5 关于报错的话 ModuleNotFoundError No m
  • Kettle案例——数据去重-不完全去重

    1 通过使用Kettle工具 创建一个转换 并添加 CSV文件输入 控件 唯一行 哈希值 控件以及Hop跳连接线 具体如图所示 2 单击 浏览 按钮 选择要进行完全去重处理的CSV文件merge csv 再单击 获取字段 按钮 Kettle
  • Java加密技术(十)——单向认证

    在 Java 加密技术 九 中 我们使用自签名证书完成了认证 接下来 我们使用第三方CA签名机构完成证书签名 这里我们使用 thawte 提供的测试用21天免费ca证书 1 要在该网站上注明你的域名 这里使用 www zlex org 作为
  • python图片对比并确定_python如何对比图像的区别

    python对比图像的区别方法 首先使用 pylab imread 读取图片 然后使用 matplotlib pylab plt imshow 显示图片 接着灰度图与RGB图相互转换 最后保存图片即可 相关学习推荐 python教程 pyt
  • Jmeter 压测工具的安装及使用

    目录 一 简介 二 下载 三 安装 四 启动 五 使用 1 调整界面显示大小 2 添加线程组 3 添加 HTTP 请求 4 添加 HTTP 请求头 5 保存压测配置 6 启动压测 7 查看结果树 8 查看聚合报告 六 补充 1 设置中文 2
  • 阿里云源 Python、npm、git、goproxy

    阿里云源 Python npm git goproxy 各种设置源的方式也都比较常见 但是根本记不住 每次都查感觉也不太好 正好发现了个宝藏地址 看起来还挺全的 以后找源也可以先在这个地方翻翻 顺便就搞了几个放到一个脚本里边 脚本内容 py
  • xxl-job项目集成到springBoot

    源码 http www xuxueli com xxl job id E4 B8 80 E3 80 81 E7 AE 80 E4 BB 8B 一初始化数据库 脚本位置 xxl job doc db tables xxl job sql xx
  • C++11中的std::function

    文章转载自 http www jellythink com archives 771 看看这段代码 先来看看下面这两行代码 std function