¿Puede una lambda que no captura nada acceder a las variables globales?

3 minutos de lectura

avatar de usuario de xmllmx
xmllmx

int n;    
int main()
{
    [](){ n = 0; }(); // clang says "ok"

    int m;
    [](){ m = 0; }(); // clang says "not ok"
}

Solo me pregunto:

Si la lambda no captura nada, ¿está permitido acceder a las variables globales según el estándar C++?

  • Supongo que sí, dado que puede usar otras cosas globales (funciones y tipos) sin capturarlas. Imagínese si tuviera que capturar funciones de algoritmos de C++ (std::find por ejemplo) para usarlos desde lambdas.

    – cdhowie

    7 de mayo de 2017 a las 4:00


  • es.cppreference.com/w/cpp/language/lambda dice algo sobre capture-default. No pude entender en detalles lo que hace.

    – taskinoor

    7 de mayo de 2017 a las 4:13

  • Si lo piensa, una lambda es solo un atajo para definir un struct con un operador de función. Las variables locales no están dentro del alcance de struct las funciones miembro, pero las variables globales sí lo son.

    – Galik

    7 de mayo de 2017 a las 4:51

  • Variables globales no poder ser capturado

    – aprendiz

    7 mayo 2017 a las 10:20

  • @cpplearner “Las variables globales no se pueden capturar. “? ¿Alguna referencia?

    – John

    2 de noviembre de 2021 a las 7:39

Avatar de usuario de Igor Tandetnik
Igor Tandetnik

Si seguro. Se aplican las reglas normales de búsqueda de nombres.

[expr.prim.lambda]/7 … con fines de búsqueda de nombres … el declaración compuesta se considera en el contexto de la expresión lambda.

Re: por qué las variables locales se tratan de manera diferente a las globales.

[expr.prim.lambda]/13 … Si un expresión lambda o una instanciación de la plantilla de operador de llamada de función de un lambda genérico odr-uses (3.2) this o una variable con duración de almacenamiento automático desde su alcance alcance, esa entidad será capturada por el expresión lambda.

[expr.prim.lambda]/9 A expresión lambda cuyo alcance más pequeño es un alcance de bloque (3.3.3) es un expresión lambda local… Los alcanzando el alcance de una expresión lambda local es el conjunto de ámbitos envolventes hasta la función envolvente más interna y sus parámetros.

En tu ejemplo, m es una variable con duración de almacenamiento automático desde el alcance de alcance de la lambda, por lo que debe capturarse. n no es, y por lo tanto no tiene que ser.

  • La cita dada no dice nada relacionado con las variables globales.

    – xmllmx

    7 de mayo de 2017 a las 4:07

  • Si n es local, el código es ilegal. ¿Por qué es legal si n es mundial?

    – xmllmx

    7 de mayo de 2017 a las 4:08


  • @xmllmx Se agregó la explicación de por qué las variables locales se comportan de manera diferente.

    – Ígor Tandetnik

    7 de mayo de 2017 a las 4:41

Avatar de usuario de Jiahao Cai
Jiahao Cai

En realidad el [](){ n = 10; }(); no captura nada, usa la variable global en su lugar.

int n;    
int main()
{
    [](){ n = 10; }(); // clang says "ok"
    std::cout << n; // output 10
}

Ver lista de captura en Explicación

lista de captura – una lista separada por comas de cero o más capturas, que opcionalmente comienza con una captura predeterminada.

La lista de captura se puede pasar de la siguiente manera (consulte a continuación para obtener una descripción detallada):

  • [a,&b] donde a se captura por copia y b se captura por referencia.
  • [this] captura el objeto actual (*this) por referencia
  • [&] captura todas las variables automáticas utilizadas en el cuerpo de la lambda por referencia y el objeto actual por referencia si existe
  • [=] captura todas las variables automáticas utilizadas en el cuerpo de la lambda por copia y objeto actual por referencia si existe
  • [ ] no captura nada

  • objeto actual por referencia si existe”? ¿Qué es eso? ¿Podría explicarlo con más detalle?

    – John

    2 de noviembre de 2021 a las 7:36

Avatar de usuario de Soumya Kanti
Soumya Kanti

Las variables globales, estáticas y constantes se acceden por defecto:

#include <iostream>

int n;    
int main()
{
    [](){ n = 10; }();
    std::cout << n << std::endl;
    static int m = 1;
    [](){ m = 100; }();
    std::cout << m << std::endl;
    const int l = 200;
    [](){ std::cout << l << std::endl; }();
}

¿Ha sido útil esta solución?