当前位置: 首页 > 编程日记 > 正文

C++11中std::function的使用

类模版std::function是一种通用、多态的函数封装。std::function的实例可以对任何可以调用的目标实体进行存储、复制、和调用操作,这些目标实体包括普通函数、Lambda表达式、函数指针、以及其它函数对象等

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

std::function实现了一套类型消除机制,可以统一处理不同的函数对象类型。以前使用函数指针来完成这些,现在可以使用更安全的std::function来完成这些任务

C++11中推出std::function是为了泛化函数对象,函数指针,引用函数,成员函数的指针,让我们可以按更统一的方式写出更加泛化的代码。

std::function对象是对C++中现有的可调用实体的一种类型安全的包裹(像函数指针这类可调用实体,是类型不安全的)。

可调用实体转换为std::function对象需要遵守以下两条原则:

(1)、std::function对象的参数能转换为可调用实体的参数;

(2)、可调用实体的返回值能转换为std::function对象的返回值(注意,所有的可调用实体的返回值都与返回void的std::function对象的返回值兼容)。

在C++中,”可调用对象”概念:(1)、是一个函数指针;(2)、是一个具有operator()成员函数的类对象(仿函数);(3)、是一个可被转换为函数指针的类对象;(4)、是一个类成员(函数)指针。

class template std::function is a general-purpose polymorphic function wrapper. Instances of std::function can store, copy, and invoke any Callable target -- functions,lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.

There are two performance implications of using std::function that might surprise you:

(1)、When calling a std::function, it does a virtual function call.

(2)、When assigning a lambda with significant captures to a std::function, it will do a dynamic memory allocation.

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

#include "function.hpp"
#include <iostream>
#include <string>
#include <functional>
#include <vector>///
// reference: http://en.cppreference.com/w/cpp/utility/functional/function
struct Foo {Foo(int num) : num_(num) {}void print_add(int i) const { std::cout << num_ + i << '\n'; }int num_;
};void print_num(int i)
{std::cout << i << '\n';
}struct PrintNum {void operator()(int i) const{std::cout << i << '\n';}
};int test_function1()
{// store a free functionstd::function<void(int)> f_display = print_num;f_display(-9);// store a lambdastd::function<void()> f_display_42 = []() { print_num(42); };f_display_42();// store the result of a call to std::bindstd::function<void()> f_display_31337 = std::bind(print_num, 31337);f_display_31337();// store a call to a member function//std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;const Foo foo(314159);//f_add_display(foo, 1);// store a call to a data member accessor//std::function<int(Foo const&)> f_num = &Foo::num_;//std::cout << "num_: " << f_num(foo) << '\n';// store a call to a member function and objectusing std::placeholders::_1;std::function<void(int)> f_add_display2 = std::bind(&Foo::print_add, foo, _1);f_add_display2(2);// store a call to a member function and object ptrstd::function<void(int)> f_add_display3 = std::bind(&Foo::print_add, &foo, _1);f_add_display3(3);// store a call to a function objectstd::function<void(int)> f_display_obj = PrintNum();f_display_obj(18);return 0;
}///
// reference: https://oopscenities.net/2012/02/24/c11-stdfunction-and-stdbind/
void execute(const std::vector<std::function<void()>>& fs)
{for (auto& f : fs)f();
}void plain_old_func()
{std::cout << "I'm an old plain function" << std::endl;
}class functor
{
public:void operator()() const{std::cout << "I'm a functor" << std::endl;}
};int test_function2()
{std::vector<std::function<void()>> x;x.push_back(plain_old_func);functor functor_instance;x.push_back(functor_instance);x.push_back([](){std::cout << "HI, I'm a lambda expression" << std::endl;});execute(x);return 0;
}///
// reference: http://shaharmike.com/cpp/lambdas-and-functions/
void global_f() {std::cout << "global_f()" << std::endl;
}struct Functor {void operator()() { std::cout << "Functor" << std::endl; }
};int test_function3()
{std::function<void()> f;std::cout << "sizeof(f) == " << sizeof(f) << std::endl;f = global_f;f();f = [](){ std::cout << "Lambda" << std::endl; };f();Functor functor;f = functor;f();return 0;
}

GitHub:https://github.com/fengbingchun/Messy_Test

相关文章:

django模板的导入

模板导入 前提:多个页面有一个相同的页面版块(多个有样式标签的集合体) 如何运用:可以将多个样式标签的集合进行封装对外提供版块的名字(接口),在有该版块的页面中直接导入即可 语法:{% include 版块页面的路径 %} 四inclusion_tag自定义标签 -- 模板导入 前提:多个页面有一个相…

[UML]UML系列——包图Package

系列文章 [UML]UML系列——用例图Use Case [UML]UML系列——用例图中的各种关系&#xff08;include、extend&#xff09; [UML]UML系列——类图Class [UML]UML系列——类图class的关联关系&#xff08;聚合、组合&#xff09; [UML]UML系列——类图class的依赖关系 [UML]UML系…

2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)

A Drawing Borders 很多构造方法&#xff0c;下图可能是最简单的了 代码&#xff1a; #include<bits/stdc.h> using namespace std; const int maxn1e610; struct Point{ int x,y; }; Point a[maxn]; int numa0; Point b[maxn]; int numb0; vector<pair<double,d…

C++11中std::bind的使用

std::bind函数是用来绑定函数调用的某些参数的。std::bind它可以预先把指定可调用实体的某些参数绑定到已有的变量&#xff0c;产生一个新的可调用实体。它绑定的参数的个数不受限制&#xff0c;绑定的具体哪些参数也不受限制&#xff0c;由用户指定。 std::bind&#xff1a;(…

在图数据上做机器学习,应该从哪个点切入?

作者 | David Mack编译 | ronghuaiyang来源 | AI公园&#xff08;ID:AI_Paradise&#xff09;【导读】很多公司和机构都在使用图数据&#xff0c;想在图上做机器学习但不知从哪里开始做&#xff0c;希望这篇文章给大家一点启发。自从我们在伦敦互联数据中心(Connected Data Lon…

C++11中Lambda表达式的使用

Lambda表达式语法&#xff1a;[capture ] ( params ) mutable exception attribute -> return-type { body } 其中capture为定义外部变量是否可见(捕获)&#xff0c;若为空&#xff0c;则表示不捕获所有外部变量&#xff0c;即所有外部变量均不可访问&#xff0c; 表示所有…

倒计时2天 | 专属技术人的盛会,为你而来!

5G 元年&#xff0c;人工智能 60 年&#xff0c;全球AI市场正发生着巨大的变化&#xff0c;顶尖科技企业和创新力量不断地进行着技术的更迭和应用的推进&#xff0c;专属于 AI 开发者的技术盛宴——2019 AI开发者大会&#xff08;AI ProCon&#xff09;将于 2 天后&#xff08;…

了解大数据的特点、来源与数据呈现方式

作业来源&#xff1a;https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2639 浏览2019春节各种大数据分析报告&#xff0c;例如&#xff1a; 这世间&#xff0c;再无第二个国家有能力承载如此庞大的人流量。http://www.sohu.com/a/290025769_313993春节人口迁徙大数据…

Mysql使用大全 从基础到存储过程

平常习惯了phpmyadmin等其他工具的的朋友有的根本就不会命令&#xff0c;如果让你笔试去面试我看你怎么办&#xff0c;所以&#xff0c;学习一下还是非常有用的&#xff0c;也可以知道你通过GUI工具的时候工具到底做了什么。Mysql用处很广&#xff0c;是php最佳拍档&#xff0c…

GDAL库简介以及在Windows下编译过程

GDAL(Geospatial Data Abstraction Library&#xff0c;地理空间数据抽象库)是一个在X/MIT许可协议下的开源栅格空间数据转换库。官网http://www.gdal.org/index.html&#xff0c;也可参考GitHub https://github.com/OSGeo/gdal&#xff0c;最新release版本为2.1.1. GDAL是一个…

Hexo博客NexT主题美化之评论系统

前言 更多效果展示&#xff0c;请访问我的 个人博客。 效果图&#xff1a; Valine 诞生于2017年8月7日&#xff0c;是一款基于Leancloud的快速、简洁且高效的无后端评论系统。 教程&#xff1a; 登录 Leancloud 官网&#xff0c;注册之后创建一个应用&#xff0c;选择【设置】-…

倒计时1天 | 专属技术人的盛会,为你而来!

5G 元年&#xff0c;人工智能 60 年&#xff0c;全球AI市场正发生着巨大的变化&#xff0c;顶尖科技企业和创新力量不断地进行着技术的更迭和应用的推进&#xff0c;专属于 AI 开发者的技术盛宴——2019 AI开发者大会&#xff08;AI ProCon&#xff09;将于 明天&#xff08;9 …

Selenium 2 WebDriver 多线程 并发

我用的是Selenium2&#xff0c;至于它的背景和历史就不赘述了。Selenium2也叫WebDriver。下面讲个例子&#xff0c;用WebDriverjava来写个自动化测试的程序。&#xff08;如果能用firefox去测试的话&#xff0c;我就直接用Selenium IDE录脚本了。。。&#xff09;有个前提&…

GDAL2.1.1库在Ubuntu14.04下编译时遇到的问题处理方法

不用作任何调整&#xff0c;直接在Linux下编译GDAL2.1.1源码的步骤是&#xff1a;$ ./configure $ make $ make install非常简单&#xff0c; 这样也能正常生成gdal动态库、静态库&#xff0c;如果想将生成的文件放到指定的目录&#xff0c;则需改第一条命令为&#xff1a;$ ./…

刷爆了!这项技术BAT力捧!程序员:我彻底慌了...

人工智能离我们还遥远吗&#xff1f;近日&#xff0c;海底捞斥资1.5亿打造了中国首家火锅无人餐厅&#xff1b;阿里酝酿了两年之久的全球首家无人酒店也正式开始运营&#xff0c;百度无人车彻底量产。李彦宏称&#xff0c;这是中国第一款能够量产的无人驾驶乘用车。而阿里的这家…

redux的compose源码,中文注释

用图片会更清楚一点,注释和代码会分的清楚源码解析参考请参考https://segmentfault.com/a/11...

做好职业规划:做自己的船长

要想在职场上有所斩获&#xff0c;就必须做好职业规划。对于职场中人来说&#xff0c;职业规划是职业发展中最关键的向导。职业规划因人而异&#xff0c;不同的对象有不同的需求&#xff0c;因此制定的目标与计划也不尽相同&#xff0c;但个人为自己做职业规划的方法和流程是大…

GDAL中GDALDataset::RasterIO分块读取的实现

GDALDataset类中的RasterIO函数能够对图像任意指定区域、任意波段的数据按指定数据类型、指定排列方式读入内存和写入文件中&#xff0c;因此可以实现对大影像的分块读、写运算操作。针对特大的影像图像&#xff0c;有时为了减少内存消耗&#xff0c;对图像进行分块读取很有必要…

掌握深度学习,为什么要用PyTorch、TensorFlow框架?

作者 | Martin Heller译者 | 弯月责编 | 屠敏来源 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;【导读】如果你需要深度学习模型&#xff0c;那么 PyTorch 和 TensorFlow 都是不错的选择。并非每个回归或分类问题都需要通过深度学习来解决。甚至可以说&#xff0c;并…

ICANN敦促业界使用DNSSEC,应对DNS劫持攻击

HTTPS加密 可以有效帮助服务器应对DNS欺骗、DNS劫持、ARP攻击等安全威胁。DNS是什么&#xff1f;DNS如何被利用&#xff1f;HTTPS如何防止DNS欺骗&#xff1f; DNS如何工作&#xff1f; 如果您想访问www.example.com&#xff0c;您的浏览器需要找到该特定Web服务器的IP地址。它…

Lucene.net: the main concepts

2019独角兽企业重金招聘Python工程师标准>>> In the previous post you learnt how to get a copy of Lucene.net and where to go in order to look for more information. As you noticed the documentation is far from being complete and easy to read. So in …

einsum,一个函数走天下

作者 | 永远在你身后转载自知乎【导读】einsum 全称 Einstein summation convention&#xff08;爱因斯坦求和约定&#xff09;&#xff0c;又称为爱因斯坦标记法&#xff0c;是爱因斯坦 1916 年提出的一种标记约定&#xff0c;本文主要介绍了einsum 的应用。简单的说&#xff…

常用排序算法的C++实现

排序是将一组”无序”的记录序列调整为”有序”的记录序列。假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序&#xff0c;这些记录的相对次序保持不变&#xff0c;即在原序列中&#xff0c;rirj&#xff0c;且ri在rj之前&#xff0…

4.65FTP服务4.66测试登录FTP

2019独角兽企业重金招聘Python工程师标准>>> FTP服务 测试登录FTP 4.65FTP服务 文件传输协议&#xff08;FTP&#xff09;&#xff0c;可以上传和下载文件。比如我们可以把Windows上的文件shan上传到Linux&#xff0c;也可以把Linux上的文件下载到Windows上。 Cent…

JavaScript的应用

DOM, BOM, XMLHttpRequest, Framework, Tool (Functionality) Performance (Caching, Combine, Minify, JSLint) ---------------- 人工做不了&#xff0c;交给程序去做&#xff0c;这样可以流程化。 Maintainability (Pattern) http://www.jmarshall.com/easy/http/ http://dj…

miniz库简介及使用

miniz&#xff1a;Google开源库&#xff0c;它是单一的C源文件&#xff0c;紧缩/膨胀压缩库&#xff0c;使用zlib兼容API&#xff0c;ZIP归档读写&#xff0c;PNG写方式。关于miniz的更详细介绍可以参考&#xff1a;https://code.google.com/archive/p/miniz/miniz.c is a loss…

iOS之runtime详解api(三)

第一篇我们讲了关于Class和Category的api&#xff0c;第二篇讲了关于Method的api&#xff0c;这一篇来讲关于Ivar和Property。 4.objc_ivar or Ivar 首先&#xff0c;我们还是先找到能打印出Ivar信息的函数&#xff1a; const char * _Nullable ivar_getName(Ivar _Nonnull v) …

亚马逊首席科学家李沐「实训营」国内独家直播,马上报名 !

开学了&#xff0c;别人家的学校都开始人工智能专业的学习之旅了&#xff0c;你呢&#xff1f;近年来&#xff0c;国内外顶尖科技企业的 AI 人才抢夺战愈演愈烈。华为开出200万年薪吸引 AI 人才&#xff0c;今年又有 35 所高校新增人工智能本科专业&#xff0c;众多新生即将开展…

人脸检测库libfacedetection介绍

libfacedetection是于仕琪老师放到GitHub上的二进制库&#xff0c;没有源码&#xff0c;它的License是MIT&#xff0c;可以商用。目前只提供了windows 32和64位的release动态库&#xff0c;主页为https://github.com/ShiqiYu/libfacedetection&#xff0c;采用的算法好像是Mult…