如下面的代码和输出所示,可以观察到三个现象:
f1
,无论是传递ff
还是&ff
,执行后都可以正常修改num_
对象中的ff
值。ff
,则执行后num_
对象中的ff
值不会被修改;如果使用占位符传递ff
或者直接绑定&ff
,都可以照常修改。Foo
,则传递ff
,执行后不修改num_
对象中的ff
值。所以我的问题是所有可调用对象都像
INVOKE(f, t1, t2, ..., tN)
一样被调用。为什么会出现以上三个差异?
#include <cstdio>
#include <functional>
#include <iostream>
using namespace std;
struct Foo
{
Foo(int num) : num_(num) {}
void print_add(int i) { num_ += i;}
int num_;
};
int main()
{
// cout << "check mem_fn" << endl;
Foo ff(1);
auto f1 = std::mem_fn(&Foo::print_add);
f1(ff, 1);
cout << "mem_fn ff, num : " << ff.num_ << endl;
f1(&ff, 1);
cout << "mem_fn &ff, num : " << ff.num_ << endl;
auto f2 = std::bind(&Foo::print_add, placeholders::_1, placeholders::_2);
f2(ff, 1);
cout << "bind placeholder_1, num : " << ff.num_ << endl;
std::function<void(int)> f3 = std::bind(&Foo::print_add, ff, placeholders::_1);
f3(1);
cout << "bind ff, num : " << ff.num_ << endl;
std::function<void(int)> f4 = std::bind(&Foo::print_add, &ff, placeholders::_1);
f4(1);
cout << "bind &ff, num : " << ff.num_ << endl;
auto f5 = std::bind(f1, placeholders::_1, placeholders::_2);
f5(ff, 1);
cout << "bind_mem_fn ff, num : " << ff.num_ << endl;
auto f6 = std::bind(f1, placeholders::_1, placeholders::_2);
f6(&ff, 1);
cout << "bind_mem_fn &ff, num : " << ff.num_ << endl;
std::function<void(Foo, int)> f7 = &Foo::print_add;
f7(ff, 1);
cout << "function(Foo) num : " << ff.num_ <<endl;
std::function<void(Foo*, int)> f8 = &Foo::print_add;
f8(&ff, 1);
cout << "function(Foo*) num : " << ff.num_ <<endl;
}
输出如下:
mem_fn ff, num : 2
mem_fn &ff, num : 3
bind placeholder_1, num : 4
bind ff, num : 4
bind &ff, num : 5
bind_mem_fn ff, num : 6
bind_mem_fn &ff, num : 7
function(Foo) num : 7
function(Foo*) num : 8
您观察到的是复制
ff
和不复制之间的区别。在所有情况下,可调用对象都会调用成员函数并修改成员。只是有时您看不到 ff
上的修改,因为修改是在 ff
的副本上。
这里:
std::function<void(Foo, int)> f7 = &Foo::print_add;
f7(ff, 1);
已制作副本。还有这里
std::function<void(int)> f3 = std::bind(&Foo::print_add, ff, placeholders::_1);
还有。