2014-06-13 39 views
5

当比较函数和仿函数,它经常被提及的是仿函数在一个函数的一个优点是仿函数是有状态的。状态数据VS全局函数

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

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

你怎么建议你把它重新开始吗? – chris

+0

@chris:你能重新配制吗? – Korchkidu

+0

对于状态使用'static'的函数,状态将在任何/所有用途和调用之间共享。根据使用情况,您可能需要一些“重置”功能。对于仿函数,您可以轻松创建许多独立的函数。 – crashmstr

回答

9

函子中的每一个实例都具有其自身的状态,而功能的静态成员将被共享。

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

+0

很清楚的答案!谢谢。 – Korchkidu

9

你已经使用了static局部变量存储状态,但只有一个国家的副本,无论你有多少次使用Accumulate。正如克里克指出的那样,初始化只能执行一次。

随着函子,每个新建的仿函数实例都有自己独立的国家,例如创建期间初始化。

即使您为函数版本的状态提供了重置机制(例如,通过将该变量移动到辅助函数名称空间,第二个函数可以对其进行修改),但您每次仍只有一个累加器。

有了函子,你有没有问题,发展如治“素数在这里得到积累,甚至还有复合材料和复合材料奇进入第三个”,在一次使用三个蓄电池。

+1

谢谢,现在更清晰!不介意我接受Dan的回答吗?两个答案都很棒,但你不需要声望了; -D – Korchkidu

+1

@Korchkidu:听起来像是一个很好的计划。 –