una tres tipos que prototipo lenguaje funciones funcion ejemplos creacion clases c++ c++11 lambda

c++ - tres - ¿Puede una lambda devolver con seguridad la dirección de una variable copiada?



tipos funciones en c++ (2)

Alguna terminología:

  • El = o & dentro de [&](){ /*..*/ } se denomina captura por defecto .
  • odr-uso de una variable significa aproximadamente que la variable no aparece en una expresión de valor descartado (como (void)some_variable o int x = some_variable, 5; ) y no ocurre en una expresión constante.
  • sentencia-compuesto es el "bloque de función" { sentencias }
  • El nombre de una variable es una expresión-id.

[expr.prim.lambda] / 3

El tipo de la expresión lambda (que también es el tipo del objeto de cierre) es un tipo de clase sin unión y sin nombre, denominado tipo de cierre , cuyas propiedades se describen a continuación.

/ 11

Si una expresión lambda tiene un valor predeterminado de captura asociado y su sentencia compuesta odr-uses (3.2) this o una variable con duración de almacenamiento automático y la entidad odr-used no se captura explícitamente, se dice que la entidad odr-used ser capturado implícitamente ;

Por lo tanto, i es capturado implícitamente.

/ 14

Una entidad se captura por copia si se captura de forma implícita y la captura por defecto es = o si se captura explícitamente con una captura que no incluye un & . Para cada entidad capturada por copia, un miembro de datos no estáticos sin nombre se declara en el tipo de cierre.

Hay un miembro de datos no estáticos (de tipo int ) en el tipo de cierre.

/ 17

Cada id-expresión que es un uso estándar (3.2) de una entidad capturada por copia se transforma en un acceso al miembro de datos correspondiente sin nombre del tipo de cierre.

Ni siquiera necesitamos interpretar esto, ya que este párrafo nos proporciona un ejemplo muy similar al de los OP:

void f(const int*); void g() { const int N = 10; [=] { int arr[N]; // OK: not an odr-use, refers to automatic variable f(&N); // OK: causes N to be captured; &N points to the // corresponding member of the closure type }; }

Si aplicamos esto al ejemplo del OP, vemos que &i refiere al miembro de datos no estáticos internos del tipo de cierre. Si el mensaje de diagnóstico es apropiado o no, no se especifica en el Estándar;)

Dado el siguiente código de muestra:

int main() { int i; auto f = [=]()mutable->int* { return &i; }; return 0; }

  1. g ++ v.4.8.1 advierte que "se devolvió la dirección de la variable local ''i''".
  2. Clang v.3.2 (Clang de MacOS) advierte que "se devolvió la dirección de la memoria de pila asociada con la variable local ''i''".
  3. Ni VS2012 ni VS2013 RC advierten de nada.

Mi comprensión de las lambdas es que el compilador generará una clase de functor. Esa clase de functor tendrá miembros para todas las variables copiadas ( i en el ejemplo). Creo que en el contexto de mi código, siempre y cuando f exista, es seguro devolver la dirección de uno de sus miembros. Me parece que todos los compiladores se equivocaron. Creo que una advertencia sobre el uso de la dirección del miembro i f después de que f se salga del alcance es válida, pero las advertencias sobre la "variable local ''i''" son incorrectas / engañosas. Estoy en lo cierto?


Sí tienes razón. El operador & está aplicando al miembro, no al objeto local.

La demostración es sencilla: simplemente modifique su ejemplo para generar las direcciones.

#include <iostream> int main() { int i; std::cout << & i << ''/n''; std::cout << [=]() mutable -> int * { return & i; } () << ''/n''; }

http://ideone.com/OqsDyg

Por cierto, esto se compila sin advertencias en -Wall en GCC 4.9.