std::function<> 和标准函数指针之间的区别?

Difference between std::function<> and a standard function pointer?

本文关键字:之间 指针 区别 函数 function lt gt std 标准      更新时间:2023-10-16

std::函数<>之间有什么区别和一个标准的函数指针?

即:

typedef std::function<int(int)> FUNCTION;
typedef int (*fn)(int);

它们实际上是一样的吗?

函数指针是C++中定义的实际函数的地址。std::function是一个包装器,可以容纳任何类型的可调用对象(可以像函数一样使用的对象)。
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允许您抽象出您正在处理的可调用对象的确切类型—您不知道它是FooFunctor,只知道它返回void,并且有一个int参数。

当您将C++与另一种脚本语言一起使用时,这种抽象非常有用。您可能希望设计一个接口,以通用的方式处理C++中定义的函数和脚本语言中定义的功能。

编辑:绑定

除了std::function,您还可以找到std::bind。这两者结合使用是非常强大的工具。

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

它们根本不一样。std::function是一个复杂、沉重、有状态、近乎魔术的类型,可以容纳任何类型的可调用实体,而函数指针实际上只是一个简单的指针。如果你能逃脱惩罚,你应该更喜欢裸函数指针或auto-bind/auto-lambda类型。只有当您确实需要一种系统化的方式来组织可调用实体的异构集合时,才能使用std::function,例如函数、函子、捕获lambda和绑定表达式。


更新:关于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); }

现在想象一下用lambda或bind表达式调用它们:

do_something_X([foo, &bar](int n){ bar += n*foo; },     12);
do_something_X(std::bind(X::bob, &jim, true, _1, Blue), 13);

使用模板的第二个版本更有效,因为在这两种情况下,参数F都被推导为表达式的实际未知类型。带有std::function的第一个版本不是一个模板,看起来可能更简单、更深思熟虑,但它总是强制构造std::function对象,并且很可能会带来多种类型的擦除和虚拟调度成本。

std::function具有状态。它可以将附加参数"绑定"到其中。

这些参数的范围可以是其他类、其他函数,甚至是成员函数调用的指针。

替换功能指针不是typedef int (*fn)(int);

它是typedef int (*fn)(void*,int);,其中void*重新呈现将被隐藏在std::function中的状态。

否。

一个是函数指针;另一个是作为函数指针的包装器的对象。

它们几乎代表相同的东西,但std::function的功能要强大得多,允许您进行绑定等等。