关于std::function 的用法: 
其实就可以理解成函数指针
1. 保存自由函数

void printA(int a)
{
cout<<a<<endl;
} std::function<void(int a)> func;
func = printA;
func(2);

2.保存lambda表达式

std::function<void()> func_1 = [](){cout<<"hello world"<<endl;};
func_1();

1).std::function可以绑定到全局函数/类静态成员函数(类静态成员函数与全局函数没有区别)。

 2).绑定到类的非静态成员函数,则需要使用std::bind。

关于std::bind 的用法: 
看一系列的文字,不如看一段代码理解的快

#include <iostream>
using namespace std;
class A
{
public:
void fun_3(int k,int m)
{
cout<<k<<" "<<m<<endl;
}
}; void fun(int x,int y,int z)
{
cout<<x<<" "<<y<<" "<<z<<endl;
} void fun_2(int &a,int &b)
{
a++;
b++;
cout<<a<<" "<<b<<endl;
} int main(int argc, const char * argv[])
{
auto f1 = std::bind(fun,1,2,3); //表示绑定函数 fun 的第一,二,三个参数值为: 1 2 3
f1(); //print:1 2 3 auto f2 = std::bind(fun, placeholders::_1,placeholders::_2,3);
//表示绑定函数 fun 的第三个参数为 3,而fun 的第一,二个参数分别有调用 f2 的第一,二个参数指定
f2(1,2);//print:1 2 3 auto f3 = std::bind(fun,placeholders::_2,placeholders::_1,3);
//表示绑定函数 fun 的第三个参数为 3,而fun 的第一,二个参数分别有调用 f3 的第二,一个参数指定
//注意: f2 和 f3 的区别。
f3(1,2);//print:2 1 3 int n = 2;
int m = 3; auto f4 = std::bind(fun_2, n,placeholders::_1);
f4(m); //print:3 4 cout<<m<<endl;//print:4 说明:bind对于不事先绑定的参数,通过std::placeholders传递的参数是通过引用传递的
cout<<n<<endl;//print:2 说明:bind对于预先绑定的函数参数是通过值传递的 A a;
auto f5 = std::bind(&A::fun_3, a,placeholders::_1,placeholders::_2);
f5(10,20);//print:10 20 std::function<void(int,int)> fc = std::bind(&A::fun_3, a,std::placeholders::_1,std::placeholders::_2); 在实际使用中都用 auto 关键字来代替std::function… 这一长串了。
fc(10,20);//print:10 20 return 0;
}

https://blog.csdn.net/liukang325/article/details/53668046

lambda 表达式

C++11中新增了lambda 表达式这一语言特性。lambda表达式可以让我们快速和便捷的创建一个”函数”。

下面是lambda表达式的语法:

[ capture-list ] { body }
[ capture-list ] ( params ) { body }
[ capture-list ] ( params ) -> ret { body } 有返回值 (ret是返回值类型)
[ capture-list ] ( params ) mutable exception attribute -> ret { body }

这其中:

  • - capture-list 是需要捕获的变量列表,用逗号分隔。其详细说明见下文。
  • - params 是lambda表达式需要的参数列表,写法和函数参数一样,不过这里不支持默认参数。
  • - ret 指明了lambda表达式的返回值。通过return语句,如果编译器能够推断出返回值的类型。或者表达式没有返回值,“-> ret”可以省略。
  • - body 函数体。
  • - mutable 当捕获列表是以复制(见下文)的形式捕获时,默认这些复制的值是const的,除非指定了mutable。
  • - exception 提供了异常的说明。
  • - attribute 对于attribute的描述可以参见这里:http://en.cppreference.com/w/cpp/language/attributes,这里不多说明。

下面,我们通过经典的Hello World示例来看一下lambda表达式:

auto lambda1 = [] {std::cout << "Hello, World!\n";};
lambda1();

这个lambda表达式将打印出字符串“Hello, World!”。

同时,我们将这个表达式赋值给“lambda1”这个变量,然后像调用函数一样,调用这个lambda表达式。

使用lambda表达式,可以让我们省却定义函数的麻烦,以inline的方式写出代码,这样的代码通常更简洁。 并且,由于阅读代码时不用寻找函数定义,这样的代码也更易读。

下面,我们来看另外一个例子。这个例子的需求是:

分两次,打印出一个vector集合中,所有:

1. 模 5 = 0

2. 大于 20

的数字。

现假设已有这个集合的定义如下:

vector<int> numbers { 1, 2, 3, 4, 5, 10, 15, 20, 25, 35, 45, 50 };

我们最先想到的方法自然是定义两个函数,分别按照上面的要求打印出需要的数字,它们的定义如下:

void printNumber1(vector<int>& numbers) {
for (const int& i : numbers) {
if (i % 5 == 0) {
cout<<i<<endl;
}
}
} void printNumber1(vector<int>& numbers) {
for (const int& i : numbers) {
if (i % 5 == 0) {
cout<<i<<endl;
}
}
}

然后,我们在需要的地方,调用它们:

printNumber1(numbers);
printNumber2(numbers);

这里逻辑上并没有问题,但是:

1. 这里我们必须先定义这个函数,才能使用。而这样的函数,可能实际上我们只会使用一次。

2. 当工程大到一定程度,我们可能不记得每个函数的实现(所以函数命名很重要,原谅我这里给函数起了很含糊的名字,你在实际上工程中,请不要这样做),为了知道每个函数的实现,我们不得不查看函数的定义,这无疑给代码的阅读造成了一定的麻烦。

下面,我们来看看使用lambda表达式如何改善上面说的问题。

使用lambda表达式,我们可以这样写:

for_each(numbers.begin(), numbers.end(), [] (int i) {
if(i % 5 == 0) {
cout<<i<<endl;
}
}); for_each(numbers.begin(), numbers.end(), [] (int i) {
if(i > 20) {
cout<<i<<endl;
}
});

这里,我们不用单独定义函数,直接以inline的方式解决了问题。并且,这段代码一气呵成,你很直观的看到了执行的逻辑。

下面,我们再详细看一下lambda表达式中的捕获列表的语法,它可能是以下几种情况中的一种:

  • [] 不捕获任何变量
  • [&] 以引用的方式捕获所有变量
  • [=] 以复制的方式捕获所有变量
  • [=, &foo] 以引用的方式捕获foo变量,但是以复制的方式捕获其他变量
  • [bar] 以复制的方式捕获bar变量,不再捕获任何其他变量
  • [this] 捕获this指针

下面,我们再以一个例子说明捕获列表的用法。

这里,我们的需求是:

打印出一个vector<int>的所有数字之和

同样的,我们先以函数的方式来解决这个问题,这个函数的定义可以是这样的:

void printSum(vector<int>& numbers) {
int sum = 0;
for (const int& i : numbers) {
sum += i;
}
cout<<sum<<endl;
}

然后,我们在需要的地方调用这个函数:

vector<int> numbers { 1, 2, 3, 4, 5, 10, 15, 20, 25, 35, 45, 50 };
printSum (numbers);

而假设我们用lambda表达式来写,这样写就可以了:

vector<int> numbers { 1, 2, 3, 4, 5, 10, 15, 20, 25, 35, 45, 50 };
int sum = 0;
std::for_each(numbers.begin(), numbers.end(), [&sum] (const int& i) { sum += i;});
cout<<sum<<endl;

这里,我们用 [&sum]以引用的形式捕获了sum这个变量,并且在lambda表达式中修改了这个变量。

这样写,是不是比定义函数的方式简洁了很多?

对于这种,能够捕获其定义时上下文变量的函数,我们称之为“闭包”,下文还将提到。

http://www.jb51.net/article/104376.htm

C++11 中function和bind以及lambda 表达式的用法的更多相关文章

  1. 【转载】C++ function、bind和lambda表达式

    本篇随笔为转载,原贴地址:C++ function.bind和lambda表达式. 本文是C++0x系列的第四篇,主要是内容是C++0x中新增的lambda表达式, function对象和bind机制 ...

  2. C++11中新特性之:lambda 表达式

    首先摆出Lambda表达式语法 lambda-expression: lambda-introducer lambda-declaratoropt compound-statementlambda-i ...

  3. C++11中的std::bind

    C++11中的std::bind 最近在看看cocos2dx的源代码,发现了cocos2dx 3.0相对于2.0改动了很多,最大的改变就是大量的使用了C++11的特性,比如auto等.其中有一个关于回 ...

  4. python lambda表达式简单用法【转】

    python lambda表达式简单用法 1.lambda是什么? 看个例子: g = lambda x:x+1 看一下执行的结果: g(1) >>>2 g(2) >>& ...

  5. C++11 中的function和bind、lambda用法

    std::function 1. std::bind绑定一个成员函数 #include <iostream> #include <functional> struct Foo ...

  6. C++11 std::function、std::bind和lambda表达式

    参考博客: C++可调用对象详解-https://www.cnblogs.com/Philip-Tell-Truth/p/5814213.html 一.关于std::function与std::bin ...

  7. (原创)c++11中 function/lamda的链式调用

    关于链式调用,比较典型的例子是c#中的linq,不过c#中的linq还只是一些特定函数的链式调用.c++中的链式调用更少见因为实现起来比较复杂.c++11支持了lamda和function,在一些延迟 ...

  8. C++ 11 std::function std::bind使用

    cocos new 出新的项目之后,仔细阅读代码,才发现了一句3.0区别于2.0的代码: auto closeItem = MenuItemImage::create( "CloseNorm ...

  9. C++11新特性之九——function、bind以及lamda表达式总结

    本文是C++0x系列的第四篇,主要是内容是C++0x中新增的lambda表达式, function对象和bind机制.之所以把这三块放在一起讲,是因为这三块之间有着非常密切的关系,通过对比学习,加深对 ...

随机推荐

  1. C#接收xmlrpc接口返回哈希表格式

    C#在调用xmlrpc接口时返回的是int值就可以直接获取,最近在调用一个接口是获取一个账号记录的详细信息,xmlrpc接口返回的是一个哈希值. 所以直接用int或者Hashtable 来获取返回值执 ...

  2. Tomcat 没有自动解压webapp下的war项目文件问题

    默认选择的tomcat安装在了C盘下的C:\Program Files下 所以webapp文件也在C盘下 选择启动tomcat时 我选择了 bin下的 Tomcat.exe 显示成功启动 打开项目网站 ...

  3. Android Annotations浅析

    这阵子遇到了好多事情,挺久没来更新博文了,这两天在学这个开源框架Android Annotations,用起来感觉挺方便的, 相信用过Spring注解的孩子理解起来应该比較easy! 就是配置起来比較 ...

  4. C# 5 in a Nutshell - Delegate

    1. What is delegate in C#? A delegate is an object that knows how to call a method.A delegate type d ...

  5. django+nginx+uwsgi 项目部署

    Django虽然自带一个Server,但只能作为开发时测试使用,我们需要一个可以稳定而持续的服务器对网站进行部署,比如Apache, Nginx, lighttpd等,本篇将利用nginx和uWSGI ...

  6. 算法笔记_071:SPFA算法简单介绍(Java)

    目录 1 问题描述 2 解决方案 2.1 具体编码   1 问题描述 何为spfa(Shortest Path Faster Algorithm)算法? spfa算法功能:给定一个加权连通图,选取一个 ...

  7. Visual studio之C#跨线程调用UI控件

    背景 当前串口通讯项目,多个线程需要同时利用richTextBoxMsg控件打印信息,直接调用会造成线程不安全,严重的时候会直接导致UI线程挂掉,因此本篇就跨线程调用UI控件做个记录. 正文 定义控件 ...

  8. HTML-HTML5+CSS3权威指南阅读(三、CSS选择器)

    1.伪元素选择器 first-line, first-letter, before, after 2.属性选择器 [attr*=val]: 如果元素的 attr 属性中包含用 val 指定的字符的话, ...

  9. Actors编程模型

    Actors模型(Actor model)首先是由Carl Hewitt在1973定义, 由Erlang OTP (Open Telecom Platform) 推广,其 消息传递更加符合面向对象的原 ...

  10. Android studio 使用心得(四)—android studio 多渠道打包(二)

    Android studio 使用心得(四)—android studio 多渠道打包 这篇文章讲了一种打包方式.是直接在android studio 里面可视化操作,结合配置文件.我个人觉得严格上来 ...