2014-06-13 46 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:聽起來像是一個很好的計劃。 –