7

Ho un progetto ObjectiveC++. Nel contesto ObjectiveC sto usando ARC e iPhoneSDK 6. In C++ sto usando un compilatore C++ 11.Uso delle funzioni lambda C++ 11 in ARC ObjectiveC++ - come farlo correttamente?

Le funzioni Lambda in C++ 11 stanno acquisendo variabili con riferimenti. Questo concetto non è realmente supportato da ObjectiveC e da "try and error" mi è venuta in mente la seguente soluzione. Ci sono delle insidie ​​di cui non sono a conoscenza?

C'è una soluzione migliore a questo problema?

typedef std::function<void()> MyLambdaType; 

... 
// m_myView will not go away. ARC managed. 
UIView * __strong m_myView; 

... 
// In Objective C context I create a lambda function that calls my Objective C object 
UIView &myViewReference = *m_myView; 
MyLambdaType myLambda = [&myViewReference]() { 
    UIView *myViewBlockScope = &myViewReference; 
    // Do something with `myViewBlockScope` 
} 

.. 
// In C++11 context I call this lambda function 
myLambda(); 
+0

Perché non utilizzare un blocco? – kennytm

+0

I blocchi AFAIK sono solo ObjectiveC o? Come posso passare un blocco a C++? –

+0

Does 'MyLambdaType myLambda = [m_myView]() {// Fai qualcosa con m_myView}' non funziona? – newacct

risposta

12

La cosa semplice da fare sarebbe quella di lasciare che la cattura lambda la variabile puntatore oggetto m_myView (Io parto dal presupposto dal frammento che si tratta di una variabile locale), e lo uso normalmente all'interno del lambda:

MyLambdaType myLambda = [m_myView]() { 
    // Do something with `m_myView` 
} 

L'unica preoccupazione sarebbe la gestione della memoria di m_myView. Per essere generalmente corretto, il lambda deve conservare m_myView quando viene creato e rilasciarlo quando viene distrutto (proprio come fanno i blocchi, perché il lambda potrebbe essere utilizzato in un ambito in cui non esiste m_myView).

Leggendo attraverso i documenti ARC, non vedo questa situazione menzionata in modo specifico, ma credo che dovrebbe gestirlo correttamente, perché (1) le variabili catturate di un lambda C++ 11 sono memorizzate come campi di un anonimo classe, che sono inizializzati al valore catturato quando viene costruito il lambda, e (2) ARC gestisce correttamente il mantenimento e il rilascio di campi oggetto Objective-C di classi C++ su costruzione e distruzione. A meno che non dica qualcosa in particolare su Lambdas in contrario, o che ci sia un bug del compilatore, non vedo perché non dovrebbe funzionare.

+4

Funziona sicuramente. La cosa complicata è che nella terminologia lambda in C++ 11, 'm_myView' viene catturato" per valore "qui. Se lo si cattura "per riferimento" (come questo: '[& m_myView]() {...}') l'oggetto 'm_myView' è * NON * mantenuto da ARC. Se ci pensate, questo ha perfettamente senso (per esempio quando si dice a C++ di catturare 'm_myView' come riferimento, C++ sta catturando un riferimento * al puntatore *, non un riferimento all'oggetto) ma la terminologia può essere un po 'confusa . – ipmcc

+0

@ipmcc: Sì. Questo è vero per l'acquisizione mediante riferimento in lambda C++ 11 in generale. Se catturi per riferimento in lambda C++ 11, non puoi usare quel lambda al di fuori dell'ambito di quelle variabili catturate. – newacct

+0

Sembra che la memoria utilizzata da m_myView non sia stata rilasciata da ARC. Ricevo un sacco di richiami ogni millisecondi nel mio codice e la mia memoria sta salendo costantemente. È lo stesso per gli oggetti Objective-C creati all'interno della funzione lambda. Perdono anche loro. –