2014-06-13 9 views
5

Quando si confrontano funzioni e funtori, viene spesso menzionato che un vantaggio di un funtore su una funzione è che un funtore è di stato.Dati di stato nei membri del functor vs funzione globale

Tuttavia, in questo codice, mi sembra che una funzione possa essere anche statica. Quindi cosa sto facendo/capendo male?

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

Come proponi di ricominciare da capo? – chris

+0

@chris: puoi riformulare per favore? – Korchkidu

+0

Con una funzione che utilizza uno stato 'statico', lo stato è condiviso su tutti/tutti gli usi e le chiamate. A seconda dell'utilizzo, potresti aver bisogno di alcune funzionalità di "reset". Per un functor, puoi facilmente creare molti che sono indipendenti. – crashmstr

risposta

9

Ogni istanza di un funtore ha il proprio stato, mentre il membro statico di una funzione viene condiviso.

Se si chiamava for_each più volte con il metodo Accumula(), il contatore non si reimpostava mai e ogni chiamata successiva iniziava dove terminava la chiamata precedente. Il functor avrebbe questo comportamento solo se ogni istanza fosse riutilizzata. La creazione di un nuovo functor risolverebbe il problema.

+0

Risposta abbastanza chiara! Grazie. – Korchkidu

9

Hai usato una variabile locale static per memorizzare lo stato, ma c'è solo una copia dello stato non importa quante volte si usa Accumulate. E come sottolinea chris, l'inizializzazione viene eseguita sempre una volta sola.

Con il functor, ogni nuova istanza di functor creata ha il proprio stato indipendente, inizializzato durante la creazione dell'istanza.

Anche se è stato fornito un meccanismo di ripristino per lo stato della versione della funzione (ad esempio, spostando la variabile in uno spazio dei nomi di supporto in cui una seconda funzione può modificarlo), si ha ancora un solo accumulatore alla volta.

Con i funtori, non si hanno problemi a sviluppare una regola come "i numeri primi vengono accumulati qui, anche i compositi lì ei compositi dispari in un terzo" che utilizza tre accumulatori alla volta.

+1

Grazie, molto più chiaro ora! Non importa se accetto la risposta di Dan? Entrambe le risposte sono ottime ma non hai più bisogno di una reputazione ;-D – Korchkidu

+1

@Korchkidu: Sembra un buon piano. –