2010-09-15 13 views
8

Come posso rilevare una variabile membro in base al valore quando si utilizzano espressioni lambda C++ 11?membro di cattura variabile per valore

L'utilizzo della sintassi [my_member] non sembra funzionare e l'acquisizione implicita utilizza il puntatore this. Quello che serve è un modo per specificare esplicitamente il tipo di cattura delle variabili membro. È possibile?

mio soluzione per ora è:

void member_function() 
{ 
    std::shared_ptr<my_member_class> my_member_copy = my_member; // this shouldn't be necessary 
    std::async([=]{ std::cout << *my_member_copy; }); 
    // std::async([=]{ std::cout << *my_member_; }); // wrong, my member could be potentially out of scope 
} 

risposta

7

non credo che si può catturare un membro per valore, è possibile catturare this ma dal momento che il membro è parte di this sarete usando una membro condiviso e non una nuova variabile.

non sapendo cosa digitare il membro è qualcosa di simile dovrebbe funzionare:

auto copy = my_member; 
std::async([copy]{ std::cout << copy; }); 

Non capisco perché si sta utilizzando un shared_ptr nel tuo esempio, se si desidera acquisire in base al valore sicuramente shared_ptr è l'ultima cosa che dovresti considerare.

+0

Ho bisogno di acquisire per valore inorder per il conteggio ref di shared_ptr da incrementare. Altrimenti l'oggetto verrà distrutto quando l'oggetto genitore viene distrutto, causando così una potenziale violazione di accesso nell'operazione asincrona. (ho dimenticato di aggiungere * nel lambda). Non vedo come il tuo esempio differisce dal mio. – ronag

+0

"Non sapendo che tipo il tuo membro è qualcosa del genere dovrebbe funzionare:", il motivo per cui ho scritto std :: shared_ptr invece di auto era esplicito riguardo al tipo di "my_member", cioè shared_ptr . – ronag

-1

In questo momento, ho affrontato lo stesso problema e risolto da solo:

  1. Cattura il puntatore this.
  2. poi scrivere this->member sintassi all'interno del lambda:

Cioè,

std::async([this]{ std::cout << this->my_member_; }); 
//   ^^^^    ^^^^^^ use this syntax 
//   | 
//   ^
//   capture `this` as well 

Funziona per me. Spero che dovrebbe funzionare anche per te. Tuttavia, non sono completamente soddisfatto di questa conoscenza. Dopo il mio lavoro, cercherò il motivo per cui è necessaria questa sintassi, o è un bug del compilatore. Sto usando GCC 4.5.0 (MinGW).

Bene, ho trovato il seguente argomento che dice che il puntatore this deve essere catturato per poter usare il membro della classe.

+4

Ma questo cattura "questo" non la variabile membro effettiva, quindi se "questo" viene cancellato causerà un comportamento indefinito. – ronag

4

Purtroppo, non credo che ci sia un modo straight-forward per fare questo, ma mi viene in mente un paio di modi per catturare un membro senza fare una copia in più.

La prima opzione è simile al vostro esempio, ma utilizza un riferimento per la variabile locale:

void member_function() 
{ 
    std::shared_ptr<my_member_class> &my_member_ref = my_member; 
    // Copied by the lambda capture 
    std::async([my_member_ref]{ std::cout << *my_member_ref; }); 
} 

Nota che c'è un bug in pre 4.6.2 versioni di GCC che causano il valore non deve essere copiato . Vedi Capturing reference variable by copy in C++0x lambda.

Un secondo approccio sarebbe quello di utilizzare bind per rendere la copia:

void member_function() 
{ 
    // Copied by std::bind 
    std::async(std::bind([](const shared_ptr<my_member_class>& my_member){ 
     std::cout << *my_member; }, my_member)); 
} 

In questo esempio, si legano renderà la propria copia my_member, e la copia viene quindi passato al espressione lambda per riferimento .

+0

Nessuno dei tuoi esempi si differenzia dal mio esempio. – ronag

+3

@ronag La differenza fondamentale tra i miei esempi e la soluzione è che i miei esempi non creano una copia extra di "my_member". Il mio primo esempio lega semplicemente il membro a un riferimento locale, permettendogli di essere catturato dal valore nella cattura lambda senza essere prima copiato. Il mio secondo esempio è stato un modo per evitare la necessità di utilizzare una variabile locale tutti insieme, utilizzando bind per acquisire 'my_member' in base al valore anziché alla cattura lambda. – rkjnsn

+0

@ronag: rkjnsn ha ragione, il suo esempio salva l'incremento/decremento/copia-puntatore quando costruisce 'my_member_copy' e dovrebbe essere quindi più veloce. Perché avresti downvotato la sua risposta? – marton78

2

Dal momento che la tua domanda è di circa C++ 11 questo non è davvero una risposta, ma in C++ 14 si può fare in questo modo:

void member_function() 
{ 
    std::async([my_member=my_member]{ std::cout << *my_member; }); 
} 

Si fa la stessa cosa come il proprio "lavoro- around "(se my_member è un shared_ptr).

0
auto& copy = my_member; 
std::async([copy]{ std::cout << copy; }); 

auto & (sopra) funziona anche e permette di evitare la copia di due volte. Sebbene questo approccio sia più sintattico che passare [this], evita di passare alla chiusura una dipendenza dall'oggetto [questo] punta a.

Problemi correlati