C++中的函数对象(C++ 11)

Gio*_*gio 7 boost functional-programming function functor c++11

我正在阅读boost::function并且我对它的使用及其与我在文档中找到的其他C++构造或术语的关系有点困惑,例如这里.

在C++(C++ 11)的上下文中,一个实例boost::function,一个函数对象,一个仿函数和一个lambda表达式有什么区别?应该何时使用哪种构造?例如,我应该何时将函数对象包装在一个boost::function而不是直接使用该对象?

以上C++是否构造了不同的方法来实现函数式语言中的闭包(一个函数,可能包含捕获的变量,可以作为值传递并由其他函数调用)?

bam*_*s53 6

函数对象和仿函数是一回事; 一个实现函数调用操作符的对象operator().lambda表达式生成一个函数对象.用的一些专门的类型的对象boost::function/ std::function也是起作用对象.

Lambda的特殊之处在于lambda表达式具有匿名和唯一类型,是创建内联函子的便捷方式.

boost::function/ std::function特别之处在于它将任何可调用实体转换为类型仅依赖于可调用实体的签名的仿函数.例如,lambda表达式每个都有一个唯一的类型,因此很难将它们传递给非泛型代码.如果您std::function从lambda 创建一个,那么您可以轻松地绕过包裹的lambda.


Ker*_* SB 6

两者boost::function和标准版本std::function都是库提供的包装器.它们可能很昂贵而且很重,如果你真的需要一异构的,可调用的实体,你应该只使用它们.只要您一次只需要一个可调用的实体,您最好使用auto或模板.

这是一个例子:

std::vector<std::function<int(int, int)>> v;

v.push_back(some_free_function);           // free function
v.push_back(&Foo::mem_fun, &x, _1, _2);    // member function bound to an object
v.push_back([&](int a, int b) -> int { return a + m[b]; });  // closure

int res = 0;
for (auto & f : v) { res += f(1, 2); }
Run Code Online (Sandbox Code Playgroud)

这是一个反例:

template <typename F>
int apply(F && f)
{
    return std::forward<F>(f)(1, 2);
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,声明apply如下是完全没有意义的:

int apply(std::function<int(int,int)>)   // wasteful
Run Code Online (Sandbox Code Playgroud)

转换是不必要的,并且模板化版本可以匹配实际(通常是不可知的)类型,例如绑定表达式或lambda表达式.