2011-01-13 21 views
31

Mi chiedo dove dovremmo usare l'espressione lambda su functor in C++. Per me, queste due tecniche sono praticamente le stesse, anche il functor è più elegante e pulito di lambda. Ad esempio, se voglio riutilizzare il mio predicato, devo copiare la parte lambda più e più volte. Quindi quando lambda entra davvero a posto?Lambda Expression vs Functor in C++

+1

BTW, non so che avrei messo "lambda" come codice. Non è una parola chiave o un tipo in C++. Esiste una "espressione lambda" ma "lambda" non è qualcosa che si vedrebbe nel codice a meno che non si stesse utilizzando la libreria lambda di boost o in realtà si fosse chiamato qualcosa nel proprio codice. –

+0

@Noah Roberts: grazie per averlo sottolineato. Modificato! Il mio punto era sottolineare la parola. – Chan

risposta

12

1) È banale e provare a condividere è più lavoro che vantaggio.

2) La definizione di un functor aggiunge semplicemente complessità (dovuta al dover creare un gruppo di variabili membro e cazzate).

Se nessuna di queste cose è vera, allora forse dovresti pensare a definire un funtore.

Modifica: sembra che sia necessario un esempio di quando sarebbe bello utilizzare un lambda su un functor. Qui si va:

typedef std::vector< std::pair<int,std::string> > whatsit_t; 

int find_it(std::string value, whatsit_t const& stuff) 
{ 
    auto fit = std::find_if(stuff.begin(), stuff.end(), [value](whatsit_t::value_type const& vt) -> bool { return vt.second == value; }); 

    if (fit == stuff.end()) throw std::wtf_error(); 

    return fit->first; 
} 

Senza lambda che avrebbe dovuto usare qualcosa che costruisce in modo simile un funtore sul posto o scrivere un oggetto funtore esterno collegabile per qualcosa che è fastidiosamente banale.

BTW, penso che wtf_error sia un'estensione.

+0

Non dimenticare di ingombrare il tuo spazio dei nomi con le classi functor. –

+2

@ Nat Nat: questo è stato risolto da spazi dei nomi anonimi. –

+0

Roberts: grazie per un bell'esempio di utilizzo di Lamda. – Chan

0

Come hai sottolineato, funziona meglio quando hai bisogno di una tantum e l'overhead di programmazione di scriverlo come una funzione non ne vale la pena.

+0

grazie per la tua risposta veloce. Ma non capisco quale sia stata la motivazione per inventare 'lamda', dal momento che penso sia più difficile da leggere e inoltre non è riutilizzabile. Non ha neanche il nome, quindi leggere il codice richiede molto più tempo. – Chan

+0

@Chan: Herb Sutter è stato uno dei sostenitori più vocali per lambda. Ha pubblicato alcuni discorsi su di loro: http://herbsutter.com/2010/10/30/pdc-languages-panel-andshortened-lambdas-talk/. Non li ho guardati da soli, ma senza dubbio ti diranno che cosa * lui * pensa di fare bene e dare alcuni esempi di quando li userebbe. –

+0

@Steve Jessop: grazie per il link. Lo guarderò. – Chan

14

Un'espressione lambda crea un funtore senza nome, è zucchero sintattico.

Quindi lo si utilizza principalmente se rende il codice un aspetto migliore. Questo in genere si verifica se (a) non si riutilizza il functor, o (b) lo si riutilizzerà, ma da un codice così totalmente estraneo al codice corrente che per condividerlo in pratica finiscono per creare my_favourite_two_line_functors.h, e avere file eterogenei dipendono da esso.

Praticamente le stesse condizioni in cui si digita qualsiasi linea (s) di codice e non astratto di tale blocco di codice in una funzione.

Detto questo, con le istruzioni range-for in C++ 0x, ci sono alcuni punti in cui dovresti aver usato un functor prima di dove potrebbe far apparire meglio il tuo codice ora per scrivere il codice come un corpo di loop, non un funtore o un lambda.

8

Piccole funzioni che non vengono ripetute.

La lamentela principale dei funtori è che non si trovano nello stesso posto in cui sono stati utilizzati. Quindi dovevi trovare e leggere il functor fuori dal contesto nel luogo in cui era usato (anche se è usato solo in un posto).

L'altro problema era che il funtore richiedeva qualche cablaggio per ottenere i parametri nell'oggetto funtore. Non complesso, ma con tutti i codici base standard. E la piastra della caldaia è suscettibile ai problemi di taglia e incolla.

Lambda provare e risolvere entrambi questi. Ma vorrei usare i funtori se la funzione è ripetuta in più punti o è più grande di (non riesco a pensare a un termine appropriato in quanto sarà sensibile al contesto) piccolo.

10

Lambdas sono fondamentalmente solo zucchero sintattico che implementa i funtori (NB: le chiusure non sono semplici.) In C++ 0x, è possibile utilizzare la parola chiave auto per archiviare lambdas localmente e std :: function ti consentirà di memorizzare lambdas, o di passarli in un modo sicuro dal tipo.

Scopri i Wikipedia article on C++0x.

0

Concettualmente, la decisione di quale utilizzare è guidato dallo stesso criterio di utilizzo di una variabile di nome rispetto a un'espressione sul posto o costante ...

size_t length = strlen(x) + sizeof(y) + z++ + strlen('\0'); 
... 
allocate(length); 
std::cout << length; 

. ..qui, la creazione di una variabile di lunghezza incoraggia il programma a considerarne la correttezza e il significato in isolamento del suo uso successivo. Il nome spera abbastanza da poter essere compreso intuitivamente e indipendentemente dal suo valore iniziale. Quindi consente di utilizzare il valore più volte senza ripetere l'espressione (mentre si gestisce z diverso). Mentre qui ...

allocate(strlen(x) + sizeof(y) + z++ + strlen('\0')); 

... il codice totale viene ridotto e il valore è localizzato nel punto in cui è necessario. L'unica cosa da "portare avanti" da una lettura di questa linea è gli effetti collaterali di allocazione e incremento (z), ma non ci sono variabili locali extra con scope o uso futuro da considerare. Il programmatore deve manipolare mentalmente meno stati continuando la loro analisi del codice.

La stessa distinzione si applica alle funzioni rispetto alle istruzioni in linea. Ai fini della risposta alla tua domanda, i funtori contro i lambda possono essere considerati solo un caso particolare di questa funzione rispetto alla decisione di inlining.