举2个例子说明bind的用法,包含了std::cref 和 std::ref
例子1:
void f(int n1, int n2, int n3, const int& n4, int n5)
{
std::cout << n1 << ' ' << n2 << ' ' << n3 << ' ' << n4 << ' ' << n5 << '\n';
}
std::cout << "1) argument reordering and pass-by-reference: ";
int n = 7;
auto f1 = std::bind(f, _2, 42, _1, std::cref(n), n);
n = 10;
f1(1, 2, 1001);
看下bind函数的参数定义
这里, bind的参数中,f是上面的函数(函数是Callable对象),_2, _1是placeholder的成员,它们分别指 f 函数中的第2个参数n2,第一个参数n1。
std::cref(n)是对n的const引用,它表示函数 f 不能对n的值做修改(如果 f 函数里面有如n++这样的改变n值的操作,是改变不了n的值的),
但是,在 f 外面可以修改n的值。由于是引用,n的变化会反映出来。
比如上面的例子,定义函数 f1 时,n = 7, 最后一个参数n是值参数,在定义时已经固定为7;std::cref(n)是const引用参数,在函数 f 外面 n的改变会影响到它的值。
f1(1,2,1001)这句分两步:
step 1: f1表示函数f, 这里的1, 2, 1001分别对应 f 函数中的n1, n2, n3,可以理解为这3个先保存在n1,n2,n3,待后面用。
step 2: std::bind(f, _2, 42, _1, std::cref(n), n), f 后面的这5个参数表示就表示实际的n1~n5了,
这个_2就是step1中保存在n2中的值,现在把它拿出来,为2;第二个参数为42;
_1是step1中保存在n1的值,把它拿出来,为1;cref(n)为n现在的值=10,最后一个n为定义bind时n的值,为7。
所以 相当于调用了f (2, 42, 1, 10, 7)
它的输出结果为:
argument reordering and pass-by-reference: 2 42 1 10 7
如果想在f 里面也能修改 n 的值,要用std::ref(n)。
例子2:
struct Foo {
void print_sum(int n1, int n2)
{
std::cout << n1+n2 << '\n';
}
int data = 10;
};
std::cout << "5) bind to a pointer to member function: ";
Foo foo;
auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
f3(5);
这里的bind中有两个函数参数,它表示把两个指针捆绑在一起,
foo就代表了Foo::print_sum, 这里f3(5) 相当于Foo::print_sum(95, 5),
输出结果:
5) bind to a pointer to member function: 100
你可能想问,我直接像例子1里一样,bind(Foo::print_sum, 95, _1)不就行了,为什么还要引入一个foo?
再看下bind函数的参数定义
f 必须是 a class of object that has a call operator, 比如a function pointer or a functor object.
如果说非要这样用bind(Foo::print_sum, 95, _1),那也可以,把print_sum函数改为static类型即可(参考)
其他例子请参考官网