我不断听说 C++ 中的函子。有人能给我概述一下它们是什么以及它们在什么情况下有用吗?
函子几乎只是一个定义了operator()
。这使您可以创建“看起来像”函数的对象:
// this is a functor
struct add_x {
add_x(int val) : x(val) {} // Constructor
int operator()(int y) const { return x + y; }
private:
int x;
};
// Now you can use it like this:
add_x add42(42); // create an instance of the functor class
int i = add42(8); // and "call" it
assert(i == 50); // and it added 42 to its argument
std::vector<int> in; // assume this contains a bunch of values)
std::vector<int> out(in.size());
// Pass a functor to std::transform, which calls the functor on every element
// in the input sequence, and stores the result to the output sequence
std::transform(in.begin(), in.end(), out.begin(), add_x(1));
assert(out[i] == in[i] + 1); // for all i
函子有几个优点。一是与常规函数不同,它们可以包含状态。上面的示例创建了一个函数,它将 42 添加到您给它的任何值上。但值 42 不是硬编码的,它是在我们创建函子实例时指定为构造函数参数的。我可以创建另一个加法器,只需使用不同的值调用构造函数即可添加 27。这使得它们可以很好地定制。
正如最后几行所示,您经常将函子作为参数传递给其他函数,例如 std::transform 或其他标准库算法。您可以对常规函数指针执行相同的操作,但正如我上面所说,函子可以“自定义”,因为它们包含状态,使它们更加灵活(如果我想使用函数指针,我必须编写一个函数它在其参数中精确地添加了 1。仿函数是通用的,并添加您初始化它时使用的任何内容),并且它们也可能更有效。在上面的例子中,编译器确切地知道哪个函数std::transform
应该打电话。它应该调用add_x::operator()
。这意味着它可以内联该函数调用。这使得它就像我在向量的每个值上手动调用该函数一样高效。
如果我传递了一个函数指针,编译器将无法立即看到它指向哪个函数,因此除非它执行一些相当复杂的全局优化,否则它必须在运行时取消引用该指针,然后进行调用。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)