C++11中std::function的使用
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.
类模版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)、是一个类成员(函数)指针。
下面是从其他文章中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 function
std::function<void(int)> f_display = print_num;
f_display(-9);
// store a lambda
std::function<void()> f_display_42 = []() { print_num(42); };
f_display_42();
// store the result of a call to std::bind
std::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 object
using 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 ptr
std::function<void(int)> f_add_display3 = std::bind(&Foo::print_add, &foo, _1);
f_add_display3(3);
// store a call to a function object
std::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
C++11中std::function的使用的更多相关文章
- C++11之std::function和std::bind
std::function是可调用对象的包装器,它最重要的功能是实现延时调用: #include "stdafx.h" #include<iostream>// std ...
- C++11 中的function和bind、lambda用法
std::function 1. std::bind绑定一个成员函数 #include <iostream> #include <functional> struct Foo ...
- C++ 中std::function 、std::bind的使用和lambda的使用
std::function是可调用对象的包装器:std::bind是将可点用对象和其参数一起进行绑定,且绑定后的结果可以使用std::function对象进行保存,并延迟调用到需要调用的时候: 在C+ ...
- 转 C++11之std::function和std::bind
std::function是可调用对象的包装器,它最重要的功能是实现延时调用: #include "stdafx.h" #include<iostream>// std ...
- C++11中std::bind的使用
std::bind: Each argument may either be bound to a value or be a placeholder: (1).If bound to a value ...
- 【浅析C++11】std::function和std::bind
目录 std::function可调用对象包装器 std::function基本用法 std::function/std::bind与抽象工厂.工厂方法的一点思考 std::function可调用对象 ...
- C++11中std::move的使用
std::move is used to indicate that an object t may be "moved from", i.e. allowing the effi ...
- C++11中std::forward的使用 (转)
std::forward argument: Returns an rvalue reference to arg if arg is not an lvalue reference; If arg ...
- C++11中std::unordered_map的使用
unordered map is an associative container that contains key-value pairs with unique keys. Search, in ...
随机推荐
- Excel-怎样实现行列转置
有时候,我们为了某些需要,必须把工作表的行列进行转置的方式显示.重新输入很浪费时间,怎样简单的实现转置呢,强大的excel2007提供了此项功能,具体怎么做,下面看我来演示一下. 工具/原料 装有 ...
- 一个简单的例子理解Kubernetes的三种IP地址类型
很多Kubernetes的初学者对Kubernetes里面三种不同的IP地址和工作机制理解得不是很清楚. 本文我们通过一个最简单的例子来学习. 用如下命令行创建一个基于nginx的deployment ...
- 如何查找Authorization object在哪些ABAP代码里使用到
使用事务码SUIM: 双击where-Used List->Authorization Objects->In Programs: 输入要查找的Authorization Object名称 ...
- python:部分内置函数与匿名函数
一.内置函数 1,数据类型:int,bool .......... 2,数据结构:dict,list,tuple,set,str 3,reversed--保留原列表,返回一个反序的迭代器 revers ...
- 【洛谷5294】[HNOI2019] 序列(主席树维护单调栈+二分)
点此看题面 大致题意: 给你一个长度为\(n\)的序列\(A\),每次询问修改一个元素(只对当前询问有效),然后让你找到一个不下降序列\(B\),使得这两个序列相应位置之差的平方和最小,并输出这个最小 ...
- LA 3415 保守的老师
题目链接:https://vjudge.net/contest/161820#problem/E 题意: 有一些同学,要从中选出一些同学来,人数尽量多,但是,两两之间要满足至少一个条件(身高差> ...
- ACM/ICPC 2018亚洲区预选赛北京赛站网络赛 B Tomb Raider 【二进制枚举】
任意门:http://hihocoder.com/problemset/problem/1829 Tomb Raider 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 L ...
- 2018.9.10 Java语言中的int及char数据类型的长度分别为(32,16 )
Byte类型 (8) Character类型(16) Integer类型 (32) Double类型 (64) Long类型 (64)
- JAVA 线程状态转换图示及说明
线程状态类型 新建状态(New):新创建了一个线程对象. 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中,变得可运行,等待获取C ...
- maven学习记录一——maven介绍及入门
1 Maven的简介 1.1 什么是maven 是apache下的一个开源项目,是纯java开发,并且只是用来管理java项目的 1.2 Maven好处 普通的传统项目 M ...