2015-12-22 16 views
6

In alcuni casi, faccio un std::find_if (ad esempio) in una funzione locale che ha 5 variabili locali, inclusi i parametri. Tuttavia, il lambda I che passa nell'algoritmo STL ha solo bisogno di accedere a 1 di questi. Ho potuto catturare questo in uno dei due modi:Quando preferire l'acquisizione esplicita in lambda rispetto alle acquisizioni implicite?

void foo(int one, int two, int three) 
{ 
    std::vector<int> m_numbers; 
    int four, five; 

    std::find_if(m_numbers.begin(), m_numbers.end(), [=](int number) { 
     return number == four; 
    }); 
} 

O posso fare:

void foo(int one, int two, int three) 
{ 
    std::vector<int> m_numbers; 
    int four, five; 

    std::find_if(m_numbers.begin(), m_numbers.end(), [four](int number) { 
     return number == four; 
    }); 
} 

(nota non ho compilare questo codice, le scuse per eventuali errori di sintassi o altri errori)

So che le acquisizioni implicite si basano sulle odr-used, quindi, dal punto di vista funzionale e di implementazione, penso che entrambe siano identiche. Quando useresti le acquisizioni esplicite su quelle implicite? Il mio unico pensiero è in qualche modo legato ai principi di incapsulamento: avere accesso solo alle cose che ti servono permette al compilatore di aiutarti a determinare quando accedi a una variabile che non dovresti. Mantiene anche lo stato locale del metodo (è invariante, per tutta la durata della funzione durante la sua esecuzione) più sicuro. Ma queste sono preoccupazioni veramente pratiche?

Esistono motivi funzionali per utilizzare le acquisizioni esplicite su quelle implicite? Che cosa è una buona regola empirica o la migliore pratica da seguire?

+2

IIRC, Scott Meyers suggerisce (nel suo libro più recente) usare praticamente solo cattura impliciti in casi come questo, in cui è un argomento per una funzione che lo usa e non lo tiene in giro. Ci sono, naturalmente, esempi di trappole in cui puoi cadere quando usi acquisizioni implicite in vari scenari. – chris

+0

Gli esempi di tali trappole sarebbero molto apprezzati. Questi esempi aiuteranno a contrastare le differenze e aiutano a stabilire buone regole generali di pratica. –

+6

@chris La raccomandazione di Scott Meyers va diversamente. Effective Modern C++, Item 31: Evita le modalità di acquisizione predefinite. – LogicStuff

risposta

2
  • cattura esplicita è sempre preferibile in quanto è meno soggetto a errori
  • E 'meglio usare & in caso di oggetti pesanti (non semplice int, double ecc)
  • Usa = quando si prevede di utilizzare il tuo lambda al di fuori della portata della cattura variabile. Con & è rischioso per arrivare penzoloni riferimento al locale distrutto variabile
2

È più semplice e più efficiente in fase di esecuzione utilizzare [=] o [&], senza nominare alcun nome.

In questi casi, come descritto da this answer, le variabili vengono acquisite solo se sono odr-used. In altre parole, il compilatore cattura solo ciò che è necessario.

Se viene specificato un elenco di cattura poi due differenze può succedere:

  • si dimentica di catturare qualcosa che il lambda utilizza
  • di catturare qualcosa che il lambda non aveva bisogno.

Nel secondo caso, se si acquisisce per valore, significa che l'oggetto viene copiato inutilmente.

Quindi, il mio consiglio sarebbe quello di utilizzare [], [&] o [=] a meno che non si possa pensare ad una buona ragione altrimenti per una situazione specifica. Uno di questi casi potrebbe essere se si desidera catturare alcune variabili per riferimento e alcune per valore.

Problemi correlati