仿函数成员中的状态数据与全局函数

时间:2014-06-13 16:53:55

标签: c++ static functor

在比较函数和函子时,经常会提到函数函数的一个优点是函数是一个有状态的。

然而,在这段代码中,在我看来,一个函数也可能是有状态的。那么我在做什么/理解错误?

struct Accumulator
{
  int counter = 0;
  int operator()(int i)
  { 
    counter += i; 
    return counter;
  }
};

int Accumulate(int i)
{
  static int counter = 0;
  counter += i;

  return counter;
};

int main()
{
  Accumulator acc;
  std::vector<int> vec{1,2,3,4};
  Accumulator acc2 = std::for_each(vec.begin(), vec.end(), acc);
  int d1 = acc(0); // 0, acc is passed by value
  int d2 = acc2(0); // 10

  std::for_each(vec.begin(), vec.end(), Accumulate);
  int d4 = Accumulate(0); // 10

  return 0;
}

2 个答案:

答案 0 :(得分:9)

您已使用static局部变量来存储状态,但无论您使用Accumulate多少次,都只有一个州的副本。正如克里斯指出的那样,初始化只执行一次。

使用仿函数,您创建的每个新仿函数实例都有自己的独立状态,在实例创建期间初始化。

即使你为函数版本的状态提供了一个重置​​机制(例如,通过将变量移动到辅助命名空间,而第二个函数可以修改它),你仍然只有一个累加器。

使用仿函数,你可以毫不费力地制定一个规则,例如“素数在这里积累,甚至在那里复合,奇数复合到第三个”,一次使用三个累加器。

答案 1 :(得分:9)

仿函数的每个实例都有自己的状态,而函数的静态成员将被共享。

如果使用Accumulate()方法多次调用for_each,计数器将永远不会重置,并且每个后续调用将从前一个调用结束的地方开始。如果重用每个实例,仿函数只会有这种行为。创建一个新的仿函数可以解决问题。