Las cookies nos permiten ofrecer nuestros servicios. Al utilizar nuestros servicios, aceptas el uso que hacemos de las cookies. Más Información. Aceptar

Qué son las funciones lambdas en C++

Daniel Sánchez Quirós
Qué son las funciones lambdas en C++
El reproductor de video será cargado en breves instantes.

En este artículo, vamos  a ver qué son las funciones lambda en C++, que fueron introducidas a partir de la versión 11, vamos a ver de forma práctica cómo utilizarlas y la gran utilidad de uso que tienen las funciones lambdas.

Qué son las funciones lambda en C++

A partir del estándar de C++ 11 se introdujeron las llamadas funciones lambda, que son funciones anónimas que son creadas en tiempo de ejecución y no en tiempo de compilación.

Cuando programamos una función normal en C++, estas funciones son generadas en tiempo de compilación, por ejemplo:

void foo()
{
    std::cout << “foo”;
}

A partir del estándar 11 de C++, se añadieron un nuevo tipo de funciones, que son generadas en tiempo de ejecución, es decir, cuando el código llega y se está ejecutando, es en ese momento cuando se crea la función.

Sintaxis de las funciones lambda en C++

Una función lambda está englobada por unos corchetes con los parámetros de captura y después, como cualquier otra función, tiene entre paréntesis sus parámetros normales. Además tiene un cuerpo, en el que podemos realizar operaciones.

Vamos a ver un ejemplo:

int main() {
    auto f = [](int& a) -> int {
        return a + 10;
    };
    return 0;
}

Aquí estamos creando una función que recibe un entero y devuelve un entero también.

Si queremos marcarle el tipo de devolución, después de los parámetros, con una flecha podemos marcarle el tipo, como hacemos en el ejemplo.

Hasta aquí todo normal, es decir, los parámetros y los parámetros de retorno pueden ser exactamente los mismos que los de una función normal, y en su cuerpo podemos hacer exactamente lo mismo que en una función normal.

¿Qué diferencia a las funciones lambda de las funciones normales?

Las diferencias son, sobre todo, los parámetros de captura, que son muy útiles.

Con estos parámetros de captura, las funciones lambda pueden capturar todo su entorno, todo el scope en el en el que han sido declaradas, y tomarlas para su cuerpo.

Ejemplos prácticos

Vamos a ver unos ejemplos de cómo utilizar las funciones lambda y sus ventajas.

int main() {
    int b = 10;
    int c = 100;
    auto f = [b, c](int& a) -> int {
        return a + 10;
    };
    return 0;
}

En este ejemplo queremos utilizar b y c para el cómputo, por lo que podemos ponerlos directamente en el cuerpo de captura.

Esto hace que, en el scope en el que está la función, busque esos dos identificadores de variables y copie todos sus parámetros dentro del scope de la función lambda.

Si en lugar de querer que los copie queremos que sea una referencia, vamos a necesitar poner el operador de referencia.

int main() {
    int b = 10;
    int c = 100;
    auto f = [&b, &c](int& a) -> int {
        return a + 10;
    };
    return 0;
}

En este caso, en lugar vez de tener una referencia, de tener una copia de b y c, vamos a tener una referencia.

Además podemos indicar que nos capture todo el scope por referencia.

int main() {
    int b = 10;
    int c = 100;
    auto f = [&](int& a) -> int {
        return a + 10;
    };
    return 0;
}

De esta forma, todo el scope que esté fuera de la función lambda, todo el scope en la que haya sido declarada, tendrá acceso a él por referencia.

De la misma forma, si queremos que sea por copia, podemos acceder a él cambiando el & por un =, con lo que nos quedaría de esta forma:

int main() {
    int b = 10;
    int c = 100;
    auto f = [=](int& a) -> int {
        return a + 10;
    };
    return 0;
}

Vamos a comprobar que todo lo explicado anteriormente funciona.

int main() {
    int b = 10;
    int c = 100;
    auto f = [&](int& a) -> int {
        b += 1;
        c +=1;
        return a + b + c;
    };
    int a = 10;
    std::cout << f(a) << std::endl;
    std::cout << b << std::endl;
    std::cout << c << std::endl;
    return 0;
}

En este caso indicamos que nos capture todo por referencia, que nos devuelva a + b + c y que imprima el resultado y además el valor de b y c.

Al ejecutarlo podemos ver los valores resultantes, que son 122, 11 y 101.

Esto es muy útil por ejemplo cuando estamos trabajando con threads. En el curso de programación genérica y programación concurrente de C ++, en el que se habla de ellos, podéis comprobar en los ejemplos como es muy útil a la hora de trabajar con cosas y compartir memoria entre threads.

Y además de todo lo anterior, vamos a ver otro ejemplo:

class Foo
{
public:
    int m_attr;
    void foo()
    {
        auto f = [this](){};
            m_attr;
        };
    };
};

En este caso tenemos una clase Foo, queremos devolver una función que tenga acceso a los parámetros de la clase, además creamos una función lambda y en el cuerpo de captura podemos indicar que capture el this. Con lo cual, inmediatamente, en la función lambda que estamos declarando, si tenemos un atributo, en el cuerpo de la función lambda podemos acceder directamente a esos atributos.

Esto es muy interesante para hacer wrappers, para enviar datos a threads y compartir los datos entre ellos, o para generar nuestras propias factorías de funciones, que se modifiquen dependiendo del scope o dependiendo de la funcionalidad que nosotros queramos.

Relacionado

Te dejamos una selección de cursos, carreras y artículos

Qué es Scope en C++

Qué es Scope en C++

Lenguajes de programación

05 de Septiembre de 2018

Cuando estamos desarrollando código, es muy importante saber cual es el alcance donde una variable puede utilizarse para que nuestro código funcione correctamente, este artículo tratamos el área de...

Por qué aprender C++

Por qué aprender C++

Lenguajes de programación

06 de Septiembre de 2018

Si están pensando en aprender a programar en C++,  te contamos los motivos por los que aprender C++ como lenguaje de programación. En este artículo vemos las ventajas y desventajas de est...

Programador en C++

carrera

Incluye 6 cursos:

  • Curso de Git, GitHub y Jekyll
  • Curso de Introducción a la programación con Pseudocódigo
  • Curso de introducción a C++

y 3 cursos más!

Duración: 23 horas y 27 minutos

Estas son algunas de las empresas que ya confían en OpenWebinars

Profesores y profesionales

Nuestros docentes son profesionales que trabajan día a día en la materia que imparten

Conviértete en profesor de OpenWebinars