C ++ Functors

我一直听到很多关于C ++函数的信息。 有人能给我一个概述,说明它们是什么以及它们会在什么情况下有用?


函子几乎就是定义operator()的类。 这可以让你创建“看起来像”一个函数的对象:

// this is a functor
struct add_x {
  add_x(int x) : x(x) {}
  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加到你给它的任何东西上。 但是这个值不是硬编码的,当我们创建我们的函数实例时,它被指定为构造函数参数。 我可以创建另一个加法器,只需通过调用具有不同值的构造函数就可以添加27个加法器。 这使得它们可以很好地定制。

如最后一行所示,您经常将函数作为参数传递给其他函数,例如std :: transform或其他标准库算法。 你可以用常规的函数指针来做同样的事情,除非像上面所说的那样,函数可以是“定制的”,因为它们包含状态,使它们更加灵活(如果我想使用函数指针,我必须编写一个函数在它的参数中加上了1,函数是一般的,并且添加了你初始化的任何东西),并且它们也可能更有效。 在上面的例子中,编译器确切地知道std::transform应该调用哪个函数。 它应该调用add_x::operator() 。 这意味着它可以内联该函数调用。 这就像我手动调用矢量的每个值的函数一样高效。

如果我传递了一个函数指针,编译器不能立即看到它指向哪个函数,所以除非它执行一些相当复杂的全局优化,否则它必须在运行时取消引用指针,然后进行调用。


几乎没有。 你可以使用boost::function来从函数和方法创建函子,如下所示:

class Foo
{
public:
    void operator () (int i) { printf("Foo %d", i); }
};
void Bar(int i) { printf("Bar %d", i); }
Foo foo;
boost::function<void (int)> f(foo);//wrap functor
f(1);//prints "Foo 1"
boost::function<void (int)> b(&Bar);//wrap normal function
b(1);//prints "Bar 1"

你可以使用boost :: bind来为这个函子添加状态

boost::function<void ()> f1 = boost::bind(foo, 2);
f1();//no more argument, function argument stored in f1
//and this print "Foo 2" (:
//and normal function
boost::function<void ()> b1 = boost::bind(&Bar, 2);
b1();// print "Bar 2"

和最有用的,用boost :: bind和boost :: function你可以从类方法创建函数,实际上这是一个委托:

class SomeClass
{
    std::string state_;
public:
    SomeClass(const char* s) : state_(s) {}

    void method( std::string param )
    {
        std::cout << state_ << param << std::endl;
    }
};
SomeClass *inst = new SomeClass("Hi, i am ");
boost::function< void (std::string) > callback;
callback = boost::bind(&SomeClass::method, inst, _1);//create delegate
//_1 is a placeholder it holds plase for parameter
callback("useless");//prints "Hi, i am useless"

您可以创建函子列表或向量

std::list< boost::function<void (EventArg e)> > events;
//add some events
....
//call them
std::for_each(
        events.begin(), events.end(), 
        boost::bind( boost::apply<void>(), _1, e));

所有这些东西都有一个问题,编译器错误消息不是人类可读的:)


Functor是一个功能类似的对象。 基本上,定义了operator()

class MyFunctor
{
   public:
     int operator()(int x) { return x * 2;}
}

MyFunctor doubler;
int x = doubler(5);

真正的好处是一个仿函数可以保持状态。

class Matcher
{
   int target;
   public:
     Matcher(int m) : target(m) {}
     bool operator()(int x) { return x == target;}
}

Matcher Is5(5);

if (Is5(n))    // same as if (n == 5)
{ ....}
链接地址: http://www.djcxy.com/p/24565.html

上一篇: C++ Functors

下一篇: explicit & implicit constructors