struct FooFunctor
{
void operator()(int i) {
std::cout << i;
}
};
// Since `FooFunctor` defines `operator()`, it can be used as a function
FooFunctor func;
std::function<void (int)> f(func);
在这里, std::function 允许你抽象出你正在处理的是什么类型的可调用对象 - 你只知道它返回 void 并且有一个 int 参数 .
void func(int a, int b) {
// Do something important
}
// Consider the case when you want one of the parameters of `func` to be fixed
// You can used `std::bind` to set a fixed value for a parameter; `bind` will
// return a function-like object that you can place inside of `std::function`.
std::function<void (int)> f = std::bind(func, _1, 5);
在该示例中, bind 返回的函数对象接受第一个参数 _1 ,并将其作为 a 参数传递给 func ,并将 b 设置为常量 5 .
4
它们完全不一样 . std::function 是一个复杂,沉重,有状态,近乎魔法的类型,可以容纳任何类型的可调用实体,而函数指针实际上只是一个简单的指针 . 如果你能逃脱它,你应该更喜欢裸函数指针或 auto - bind / auto -lambda类型 . 如果你真的需要一种系统的方法来组织可调用实体的异构集合,例如函数,函子,捕获lambdas和绑定表达式,那么只使用 std::function .
更新:关于 auto 类型的一些解释:比较以下两个函数:
void do_something_1(std::function<void(int)> f, int a) { f(a); }
template <typename F, typename A> void do_something_2(F f, A a) { f(a); }
4 回答
函数指针是C中定义的实际函数的地址 .
std::function
是一个包装器,可以容纳任何类型的可调用对象(可以像函数一样使用的对象) .在这里,
std::function
允许你抽象出你正在处理的是什么类型的可调用对象 - 你只知道它返回void
并且有一个int
参数 .这个抽象很有用的一个真实例子就是当你将C与另一种脚本语言结合使用时 . 您可能希望设计一个接口,该接口可以通用方式处理C中定义的函数以及脚本语言中定义的函数 .
Edit: 绑定
除了
std::function
,您还可以找到std::bind
. 这两个是一起使用时非常强大的工具 .在该示例中,
bind
返回的函数对象接受第一个参数_1
,并将其作为a
参数传递给func
,并将b
设置为常量5
.它们完全不一样 .
std::function
是一个复杂,沉重,有状态,近乎魔法的类型,可以容纳任何类型的可调用实体,而函数指针实际上只是一个简单的指针 . 如果你能逃脱它,你应该更喜欢裸函数指针或auto
-bind
/auto
-lambda类型 . 如果你真的需要一种系统的方法来组织可调用实体的异构集合,例如函数,函子,捕获lambdas和绑定表达式,那么只使用std::function
.更新:关于
auto
类型的一些解释:比较以下两个函数:现在想象一下用lambda或
bind
表达式调用它们:带有模板的第二个版本更有效,因为在这两种情况下,参数
F
都被推导为表达式的实际不可知类型 . 带有std::function
的第一个版本不是模板,可能看起来更简单,更有意思,但它总是强制构造std::function
对象,并且很可能带有多种类型的擦除和虚拟调度成本 .std::function
有州 . 它可以包含其他参数"bound" .这些参数的范围可以是其他类,其他函数,甚至是成员函数调用的指针 .
替换函数指针不是
typedef int (*fn)(int);
它是
typedef int (*fn)(void*,int);
,void*
重新排列将隐藏在std::function
中的状态 .没有 .
一个是函数指针;另一个是一个对象,用作函数指针的包装器 .
它们几乎代表相同的东西,但
std::function
更强大,允许你做绑定和诸如此类的东西 .