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, calling the returned function object will always use that value as argument;
(2)、If a placeholder, calling the returned function object forwards an argument passed to the call (the one whose order number is specified by the placeholder).
std::bind receives a pointer to a function (it also can be a lambda expression or a functor) and receives a list of parameters that pass it to the function. As result, bind returns a new function object with a different prototype because all the parameters of the function were already specified.
A placeholder is an object that specifies the number of parameter in the bound function that will be used to enter this parameter.
std::bind is a Standard Function Objects that acts as a Functional Adaptor i.e. it takes a function as input and returns a new function Object as an output with with one or more of the arguments of passed function bound or rearranged.
std::bind函数是用来绑定函数调用的某些参数的。std::bind它可以预先把指定可调用实体的某些参数绑定到已有的变量,产生一个新的可调用实体。它绑定的参数的个数不受限制,绑定的具体哪些参数也不受限制,由用户指定。
std::bind:(1)、将函数、成员函数和闭包转成function函数对象;(2)、将多元(n>1)函数转成一元函数或者(n-1)元函数。
std::bind本身是一种延迟计算的思想,它本身可以绑定普通函数、全局函数、静态函数、类静态函数甚至是类成员函数。无法使用std::bind绑定一个重载函数的参数,必须显式地指出需要绑定的重载函数的版本。成员函数区别于普通函数的一个特殊之处在于,其第一个参数必须是该类型的一个对象(或对象的指针或引用)。
std::bind接受一个函数(或者函数对象,或者任何你可以通过"(…)"符号调用的事物),生成一个其有某一个或多个函数参数被”绑定”或重新组织的函数对象。绑定的参数将会以值传递的方式传递给具体函数,占位符将会以引用传递。
std::bind需要注意事项:
(1)、bind预先绑定的参数需要传具体的变量或值进去,对于预先绑定的参数,是pass-by-value的;
(2)、对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增。placeholder是pass-by-reference的;
(3)、bind的返回值是可调用实体,可以直接赋给std::function对象;
(4)、对于绑定的指针、引用类型的参数,使用者需要保证在可调用实体调用之前,这些参数是可用的;
(5)、类的this可以通过对象或者指针来绑定。
下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:
#include "bind.hpp" #include <iostream> #include <string> #include <functional> // std::bind #include <random> #include <memory> #include <algorithm> ////////////////////////////////////////////////// // reference: http://en.cppreference.com/w/cpp/utility/functional/bind static void f(int n1, int n2, int n3, const int& n4, int n5) { std::cout << n1 << ' ' << n2 << ' ' << n3 << ' ' << n4 << ' ' << n5 << '\n'; } static int g(int n1) { return n1; } struct Foo_bind { void print_sum(int n1, int n2) { std::cout << n1 + n2 << '\n'; } int data = 10; }; int test_bind1() { using namespace std::placeholders; // for _1, _2, _3... // demonstrates argument reordering and pass-by-reference int n = 7; // (_1 and _2 are from std::placeholders, and represent future // arguments that will be passed to f1) auto f1 = std::bind(f, _2, _1, 42, std::cref(n), n); n = 10; f1(1, 2, 1001); // 1 is bound by _1, 2 is bound by _2, 1001 is unused // makes a call to f(2, 1, 42, n, 7) // nested bind subexpressions share the placeholders auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5); f2(10, 11, 12); // common use case: binding a RNG with a distribution std::default_random_engine e; std::uniform_int_distribution<> d(0, 10); std::function<int()> rnd = std::bind(d, e); // a copy of e is stored in rnd for (int n = 0; n<10; ++n) std::cout << rnd() << ' '; std::cout << '\n'; // bind to a pointer to member function Foo_bind foo; auto f3 = std::bind(&Foo_bind::print_sum, &foo, 95, _1); f3(5); // bind to a pointer to data member auto f4 = std::bind(&Foo_bind::data, _1); std::cout << f4(foo) << '\n'; // smart pointers can be used to call members of the referenced objects, too //std::cout << f4(std::make_shared<Foo_bind>(foo)) << '\n' // << f4(std::make_unique<Foo_bind>(foo)) << '\n'; return 0; } /////////////////////////////////////////////////// // reference: http://www.cplusplus.com/reference/functional/bind/ // a function: (also works with function object: std::divides<double> my_divide;) double my_divide(double x, double y) { return x / y; } struct MyPair { double a, b; double multiply() { return a*b; } }; int test_bind2() { using namespace std::placeholders; // adds visibility of _1, _2, _3,... // binding functions: auto fn_five = std::bind(my_divide, 10, 2); // returns 10/2 std::cout << fn_five() << '\n'; // 5 auto fn_half = std::bind(my_divide, _1, 2); // returns x/2 std::cout << fn_half(10) << '\n'; // 5 auto fn_invert = std::bind(my_divide, _2, _1); // returns y/x std::cout << fn_invert(10, 2) << '\n'; // 0.2 auto fn_rounding = std::bind<int>(my_divide, _1, _2); // returns int(x/y) std::cout << fn_rounding(10, 3) << '\n'; // 3 MyPair ten_two{ 10, 2 }; // binding members: auto bound_member_fn = std::bind(&MyPair::multiply, _1); // returns x.multiply() std::cout << bound_member_fn(ten_two) << '\n'; // 20 auto bound_member_data = std::bind(&MyPair::a, ten_two); // returns ten_two.a std::cout << bound_member_data() << '\n'; // 10 return 0; } ///////////////////////////////////////////////// // reference: https://oopscenities.net/2012/02/24/c11-stdfunction-and-stdbind/ static void show(const std::string& a, const std::string& b, const std::string& c) { std::cout << a << "; " << b << "; " << c << std::endl; } int test_bind3() { using namespace std::placeholders; // Thanks to the placeholders, you can change the order of the arguments passed as parameters to a bound function. auto x = bind(show, _1, _2, _3); auto y = bind(show, _3, _1, _2); auto z = bind(show, "hello", _2, _1); x("one", "two", "three"); y("one", "two", "three"); z("one", "two"); return 0; } ///////////////////////////////////////////////////// // reference: http://stackoverflow.com/questions/22422147/why-is-stdbind-not-working-without-placeholders-in-this-example-member-functi static void f_(int a, int b, int c) { fprintf(stdout, "a = %d, b = %d, c = %d\n", a, b, c); } struct foo_bind { void f() const { fprintf(stdout, "foo_bind\n"); }; }; int test_bind4() { using namespace std::placeholders; // The first parameter of std::bind() is the function to be called, and the rest are the arguments of the call. std::function<void()> f_call = std::bind(f_, 1, 2, 3); f_call(); //Equivalent to f_(1,2,3) // If you need to specify that some parameters have to be specified at the call point, // you have to use placeholders to represent that parameters std::function<void(int, int, int)> f_call2 = std::bind(f_, _1, _2, _3); f_call2(1, 2, 3); //Same as f_(1,2,3) // Note that the numbers of the placeholders specify the number of the parameter at the call point. // The first parameter of the call point is identified by _1, the second by _2, and so on. // This could be used to specify parameters in different ways, reordering the parameters of a function call, etc. std::function<void(int, int)> f_call3 = std::bind(f_, _1, 2, _2); f_call3(1, 3); //Equivalent to f_( 1 , 2 , 3 ); std::function<void(int, int, int)> reordered_call = std::bind(f_, _3, _2, _1); reordered_call(3, 2, 1); //Same as f_( 1 , 2 , 3 ); // std::bind() could be used to bind a member function to the object used to call it foo_bind myfoo; std::function<void()> f = std::bind(&foo_bind::f, std::cref(myfoo)); f(); return 0; } ///////////////////////////////////////////////// // reference: https://msdn.microsoft.com/en-us/library/bb982702.aspx static void square(double x) { std::cout << x << "^2 == " << x * x << std::endl; } static void product(double x, double y) { std::cout << x << "*" << y << " == " << x * y << std::endl; } int test_bind5() { using namespace std::placeholders; double arg[] = { 1, 2, 3 }; std::for_each(&arg[0], arg + 3, square); std::cout << std::endl; std::for_each(&arg[0], arg + 3, std::bind(product, _1, 2)); std::cout << std::endl; std::for_each(&arg[0], arg + 3, std::bind(square, _1)); return (0); }
GitHub:https://github.com/fengbingchun/Messy_Test
C++11中std::bind的使用的更多相关文章
- C++11中std::function的使用
class template std::function is a general-purpose polymorphic function wrapper. Instances of std::fu ...
- c++11之std::bind简单使用
note 更多用法,请参考: cppreference 用的少,容易忘. 我的理解 类似延迟计算. 比如,回调函数,将回调函数传入后,回调函数不一定马上被调用. 它是一个模板类,调用后将生成一个新的调 ...
- C++11中std::move的使用
std::move is used to indicate that an object t may be "moved from", i.e. allowing the effi ...
- 第11课 std::bind和std::function(2)_std::bind绑定器
1. 温故知新:std::bind1st和std::bind2nd (1)bind1st.bind2nd首先它们都是函数模板,用于将参数绑定到可调用对象(如函数.仿函数等)的第1个或第2个参数上. ( ...
- 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 ...
- 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::move、std::forward、左右值引用、移动构造函数的测试
关于C++11新特性之std::move.std::forward.左右值引用网上资料已经很多了,我主要针对测试性能做一个测试,梳理一下这些逻辑,首先,左值比较熟悉,右值就是临时变量,意味着使用一次就 ...
- 用C++11的std::async代替线程的创建
c++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的: void f(int n); std::thread t(f, n + 1); t.join(); 但是线程毕竟是属于比 ...
随机推荐
- 别跑了,看看脚下有木有money
别跑了,看看脚下有木有money 1.长大论坛 本来是想做个博客的,无奈级别不够,博客过于复杂,所以就做了这个类似于贴吧的东西.在这里,你可以发帖:可以吐槽学校.可以向他人寻求帮助.甚至可以 ...
- 第一次团队合作,对Scrum的初步了解
学习和运用scrum 作为长大的大三老腊肉,我们已经在长大生活了两年多,对于什么是长大人最想完善的校园需求.最想拥有的校园服务媒介也有了更加深切的体会. 于是,GoodJob小团队blingbling ...
- 数字(int)转字符串和字符串转数字(int)
室友去面试,问了一个字符串转成数字的算法题,室友没搞出来,我心想,这个不是很简单的吗?于是动手在纸上画了画代码.画完后,总感觉哪里不对,最后一个个挖掘,才发现,尼玛,这到处都是坑啊---特此记录一下中 ...
- Android(java)学习笔记47:通过反射获得构造方法并且使用
1. 获取字节码文件对象: Class c = Class.forName("cn.itcast_01.Person"); 2. 获取构造方法 ...
- 【SNOI2017】炸弹
题目大意 在一条直线上有\(N\)个炸弹,每个炸弹的坐标是\(X_i\),爆炸半径是 \(R_i\), 当一个炸弹爆炸时,如果另一个炸弹所在位置\(X_j\)满足: $ X_i-R_i\leq X_j ...
- JDBC执行存储过程的四种情况 (转)
本文主要是总结 如何实现 JDBC调用Oracle的存储过程,从以下情况分别介绍: [1].只有输入IN参数,没有输出OUT参数 [2].既有输入IN参数,也有输出OUT参数,输出是简单值(非列表) ...
- iOS程序的启动原理
一.在一些老的项目中,有很多不是通过代码添加窗口和跟控制器.是通过设置MainInterface(设置最主要的xib),在xib中通过图形化的操作设置应用程序的代理->设置窗口->设置根控 ...
- PHP中级面试经历
资源来自网络:http://www.2cto.com/kf/201304/204749.html 1.用PHP打印出前一天的时间格式是2006-5-10 22:21:21(2分) 2.echo(),p ...
- Dependency Injection in ASP.NET Web API 2 (在web api2 中使用依赖注入)
原文:http://www.asp.net/web-api/overview/advanced/dependency-injection 1 什么是依赖注入(Dependency Injection) ...
- .NET MVC伪静态
说明:MVC中的伪静态跟我们的WebForm里面的伪静态不一样(详情:配置伪静态(URL重写)) 由于我们的MVC中存在路由,所以我们不必去处理每个访问的页面进行重写,我们完全可以再配置一个路由让他显 ...