2010-02-28 16 views
11

Vedo oggetti funzione usati spesso insieme agli algoritmi STL. Gli oggetti funzione sono stati creati a causa di questi algoritmi? Quando usi un oggetto funzione in C++? Quali sono i suoi benefici?Quando si usano oggetti funzione in C++?

+0

Vedere anche: http://stackoverflow.com/questions/356950/c-functors-and-their-uses –

risposta

9

Come detto jdv, al posto dei puntatori di funzione vengono utilizzati i funtori, che sono più difficili da ottimizzare e inline per il compilatore; inoltre, un vantaggio fondamentale dei funtori è che possono facilmente mantenere uno stato tra le chiamate a loro , in modo che possano lavorare in modo diverso a seconda delle altre volte in cui sono stati chiamati, tenere traccia di alcuni parametri utilizzati, .. .

ad esempio, se si desidera sommare tutti gli elementi in due contenitori di interi si può fare qualcosa di simile:

struct 
{ 
    int sum; 
    void operator()(int element) { sum+=element; } 
} functor; 
functor.sum=0; 
functor = std::for_each(your_first_container.begin(), your_first_container.end(), functor); 
functor = std::for_each(your_second_container.begin(), your_second_container.end(), functor); 
std::cout<<"The sum of all the elements is: "<<functor.sum<<std::endl; 

  1. in realtà, come R Samuel Klatchko sottolineato qui di seguito, possono supportare più statistiche indipendenti es, uno per ogni istanza di functor:
    Una dichiarazione leggermente più precisa è che i funtori possono supportare più stati indipendenti (le funzioni possono supportare un singolo stato tramite statica/globalità che non è né thread-safe né rientranti).
    I Funcitors consentono di utilizzare stati ancora più complicati, ad esempio uno stato condiviso (campi statici) e uno stato privato (campi di istanza). Tuttavia questa ulteriore flessibilità è raramente utilizzata.
+2

Un'affermazione leggermente più precisa è che i funtori possono supportare più stati indipendenti (le funzioni possono supportare un singolo stato tramite statica/globalità che non è né thread-safe né rientranti). –

+0

Sicuramente vuoi dire che i puntatori di funzione sono più difficili da ottimizzare e in linea? Il modo in cui è scritto ora, è un po 'oscuro. – jalf

+0

Intendevo dire che i puntatori di funzione sono più difficili da ottimizzare e inline; non mi sembra poco chiaro, "che" si riferisce all'ultima frase della frase precedente, cioè "puntatori di funzione". Tuttavia, se vuoi suggerire una frase migliore, sarò lieto di modificare. :) –

2

Gli oggetti funzione sono stati progettati per consentire un forte livello di astrazione rispetto a STL e, a tale proposito, sono eccezionali.

Tuttavia, io preferisco usare boost::bind e associare una funzione per gli algoritmi STL invece - di solito (anche se non nei casi in cui l'oggetto ha uno stato) che sembra una soluzione più elegante.

std::for_each(callback.begin(), callback.end(), 
    boost::bind(&Callback::call(),_1) 
); 

Inoltre, un altro imminente alternativa sono lambda di a C++ 0x (esempio spudoratamente rubato da Wikipedia):

std::vector<int> someList; 
int total = 0; 
std::for_each(someList.begin(), someList.end(), [&total](int x) { 
    total += x; 
}); 
std::cout << total; 

Si noti che a causa della chiusura, che non hanno la limitazione di BIND su non avere uno stato.

8

Gli oggetti di funzione (funtori) vengono in genere utilizzati al posto dei puntatori di funzione. I puntatori di funzione hanno il problema che il compilatore in genere li passa come puntatori grezzi, il che rende difficile per il compilatore inline il codice in seguito. E sono più facili da fornire i parametri.

+0

+1 - Per la menzione dell'inlinazione –

+0

Quindi suppongo che i funtori siano usati di più per la loro efficienza ... – jasonline

+0

@jasonline: Questo non è l'unico vantaggio, ma in molti casi è il vantaggio principale. –

1

Non posso dire perché sono venuti fuori - forse semplicemente perché potevano!

Quando si utilizza un funtore? Considera che un functor sta semplicemente spostando il codice che avresti normalmente inserito in un ciclo nell'operatore() di una classe, non sono molto diversi dal semplice chiamare una funzione in un ciclo while ... eccetto che, usandoli consenti al compilatore di incorporare il codice e puoi anche passare un oggetto pre-costruito, che hai costruito con un certo stato. Quest'ultimo punto li rende molto potenti.

Confrontare l'algoritmo di ordinamento con la chiamata qsort CRT. Fanno la stessa cosa, lo fanno solo in modo abbastanza diverso.

2

Un oggetto funzione è una funzione che è anche un oggetto, ovvero ha uno stato.Le normali funzioni generalmente non hanno stato. Possono emulare lo stato accedendo a variabili globali, ma lo stato viene condiviso tra tutte le chiamate.

2

L'idea di incapsulare una funzione come oggetto risale a Lisp e Smalltalk. L'idea C++ di functor era un capitolo del libro di Jim Coplien Advanced C++ Programming Styles and Idioms nel 1991. STL usò l'idioma e lo rese popolare ulteriormente.

1

This article ha uno sguardo approfondito sugli oggetti funzione e su come può rendere il codice molto più potente e più pulito.

Problemi correlati