C++11中std::bind的使用
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可以通過對象或者指針來綁定。
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.
下面是從其他文章中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-referenceint 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 placeholdersauto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5);f2(10, 11, 12);// common use case: binding a RNG with a distributionstd::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 rndfor (int n = 0; n<10; ++n)std::cout << rnd() << ' ';std::cout << '\n';// bind to a pointer to member functionFoo_bind foo;auto f3 = std::bind(&Foo_bind::print_sum, &foo, 95, _1);f3(5);// bind to a pointer to data memberauto 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/2std::cout << fn_five() << '\n'; // 5auto fn_half = std::bind(my_divide, _1, 2); // returns x/2std::cout << fn_half(10) << '\n'; // 5auto fn_invert = std::bind(my_divide, _2, _1); // returns y/xstd::cout << fn_invert(10, 2) << '\n'; // 0.2auto fn_rounding = std::bind<int>(my_divide, _1, _2); // returns int(x/y)std::cout << fn_rounding(10, 3) << '\n'; // 3MyPair 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'; // 20auto bound_member_data = std::bind(&MyPair::a, ten_two); // returns ten_two.astd::cout << bound_member_data() << '\n'; // 10return 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 parametersstd::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 itfoo_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的
- 下一篇: C++11中Lambda表达式的使用