在比较函数和函子时,经常会提到函数函数的一个优点是函数是一个有状态的。
然而,在这段代码中,在我看来,一个函数也可能是有状态的。那么我在做什么/理解错误?
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;
}
答案 0 :(得分:9)
您已使用static
局部变量来存储状态,但无论您使用Accumulate
多少次,都只有一个州的副本。正如克里斯指出的那样,初始化只执行一次。
使用仿函数,您创建的每个新仿函数实例都有自己的独立状态,在实例创建期间初始化。
即使你为函数版本的状态提供了一个重置机制(例如,通过将变量移动到辅助命名空间,而第二个函数可以修改它),你仍然只有一个累加器。
使用仿函数,你可以毫不费力地制定一个规则,例如“素数在这里积累,甚至在那里复合,奇数复合到第三个”,一次使用三个累加器。
答案 1 :(得分:9)
仿函数的每个实例都有自己的状态,而函数的静态成员将被共享。
如果使用Accumulate()方法多次调用for_each
,计数器将永远不会重置,并且每个后续调用将从前一个调用结束的地方开始。如果重用每个实例,仿函数只会有这种行为。创建一个新的仿函数可以解决问题。