2010-09-15 12 views
8

¿Cómo puedo capturar una variable miembro por valor cuando uso C++ 11 expresiones lambda?variable de miembro de captura por valor

El uso de la sintaxis [my_member] no parece funcionar, y la captura implícita utiliza el puntero this. Lo que se necesita es una forma de especificar explícitamente el tipo de captura de las variables miembro. ¿Es eso posible?

Mi solución por ahora es:

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 
} 

Respuesta

7

no creo que pueda capturar un miembro de valor, puede capturar this pero dado que el elemento es parte de this que va a utilizar una miembro compartido y no una nueva variable.

no saber lo que escriba su miembro es algo como esto debería funcionar:

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

No entiendo por qué estás usando un shared_ptr en su ejemplo, si se desea capturar por valor seguramente es shared_ptr lo último que debes considerar

+0

Necesito capturar por valor en el orden para que se incremente el conteo de ref compartido. De lo contrario, el objeto se destruirá cuando se destruya el objeto principal, lo que provocará una posible infracción de acceso en la operación asincrónica. (se olvidó de agregar * en la lambda). No veo cómo tu ejemplo difiere del mío. – ronag

+0

"No sé de qué tipo es su miembro algo así debería funcionar:", la razón por la que escribí std :: shared_ptr en lugar de auto era ser explícito sobre el tipo de "mi_miembro", es decir shared_ptr . – ronag

-1

En este momento, se enfrentan el mismo problema y lo resolvió a mí mismo:

  1. captura el puntero this.
  2. luego escribir this->member sintaxis dentro de la lambda:

Es decir,

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

Funciona para mí. Espero que te funcione también. Sin embargo, no estoy completamente satisfecho con este conocimiento. Después de mi trabajo, buscaré la razón por la cual se requiere esta sintaxis, o es un error del compilador. Estoy usando GCC 4.5.0 (MinGW).

Bueno, encontré el siguiente tema que dice this puntero se debe capturar para utilizar el miembro de la clase.

+4

Pero esto captura "esta" no la variable de miembro real, por lo que si se elimina "this", se producirá un comportamiento indefinido. – ronag

4

Por desgracia, no creo que hay una manera recta hacia adelante para hacer esto, pero puedo pensar en un par de maneras de capturar un miembro sin hacer una copia extra.

La primera opción es similar a su ejemplo, pero utiliza una referencia para la variable local:

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; }); 
} 

Tenga en cuenta que hay un error en la pre 4.6.2 versiones de GCC que causan el valor no debe ser copiado . Ver Capturing reference variable by copy in C++0x lambda.

Un segundo enfoque sería el uso de bind para hacer 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)); 
} 

En este ejemplo, se unen hará su propia copia de my_member, y esta copia a continuación, se pasa a la expresión lambda por referencia .

+0

Ninguno de sus ejemplos difiere de mi ejemplo. – ronag

+3

@ronag La diferencia clave entre mis ejemplos y su solución alternativa es que mis ejemplos no hacen una copia adicional de 'mi_miembro'. Mi primer ejemplo simplemente vincula al miembro a una referencia local, lo que permite que se capture por valor en la captura lambda sin que se copie primero. Mi segundo ejemplo fue una forma de evitar la necesidad de usar una variable local en conjunto, usando bind para capturar 'my_member' por valor en lugar de la captura lambda. – rkjnsn

+0

@ronag: rkjnsn tiene razón, su ejemplo guarda el incremento/decremento/copia de puntero al construir 'my_member_copy' y debería ser así más rápido. ¿Por qué rechazarías su respuesta? – marton78

2

Debido a que su pregunta es acerca de C++ 11 esto no es realmente una respuesta, pero en C++ 14 se puede hacer de esta manera:

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

Se hace lo mismo como su propio "de obra alrededor "(si my_member es un shared_ptr).

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

automático & (arriba) también funciona y evita copiar dos veces. Aunque este enfoque es más sintaxis que pasar [esto], evita pasar al cierre una dependencia del objeto al que [este] apunta.

Cuestiones relacionadas