El lenguaje C++ es conocido por su potencia y flexibilidad, y una de las características que refuerza esta reputación es la introducción de las expresiones lambda. Estas funciones anónimas y ligeras permiten escribir código más limpio y conciso, especialmente en escenarios donde se necesitan funciones pequeñas y de un solo uso.
Una lambda es una función anónima que se puede definir en línea en el lugar donde se utiliza. Las lambdas permiten crear pequeñas funciones sin necesidad de nombrarlas o declararlas previamente. Fueron introducidas en C++11 y han sido una herramienta clave para el desarrollo moderno en C++.
La sintaxis básica de una lambda en C++ es :
[captura](parametros) -> tipo_retorno {
// cuerpo de la lambda
};
- [captura]: Define cómo la lambda captura las variables del entorno en el que se declara.
- (parametros): Lista de parámetros que la lambda acepta.
- -> tipo_retorno: Especifica el tipo de retorno de la lambda (puede omitirse si el compilador puede inferirlo).
- { cuerpo }: El código que define la función de la lambda.
Veamos un ejemplo simple de una lambda que suma dos números:
#include <iostream>
int main() {
auto suma = [](int a, int b) -> int {
return a + b;
};
std::cout << "La suma de 3 y 4 es: " << suma(3, 4) << std::endl;
return 0;
}
En este ejemplo, la lambda captura dos parámetros `a` y `b`, y retorna su suma.
Una de las características más poderosas de las lambdas es su capacidad para capturar variables del entorno donde son definidas. Hay varias formas de hacerlo:
- Captura por valor: `[x]` captura `x` por valor.
- Captura por referencia: `[&x]` captura `x` por referencia.
- Captura todo por valor: `[=]` captura todas las variables que se usan en la lambda por valor.
- Captura todo por referencia: `[&]` captura todas las variables que se usan en la lambda por referencia.
#include <iostream>
int main() {
int x = 10;
int y = 20;
auto suma = [x, &y]() {
y = x + y;
};
suma();
std::cout << "El nuevo valor de y es: " << y << std::endl; // Imprime 30
return 0;
}
Aquí, `x` se captura por valor, y `y` se captura por referencia, lo que significa que cualquier modificación de `y` dentro de la lambda afecta a `y` fuera de la lambda.
Las lambdas son particularmente útiles cuando se combinan con las funciones de la STL (Standard Template Library) como `std::sort`, `std::for_each`, etc.
Por ejemplo, ordenar un vector de enteros en orden descendente usando `std::sort` y una lambda:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {3, 1, 4, 1, 5, 9};
std::sort(vec.begin(), vec.end(), [](int a, int b) {
return a > b; // Orden descendente
});
for (int n : vec) {
std::cout << n << " "; // Imprime: 9 5 4 3 1 1
}
return 0;
}
Por defecto, las variables capturadas por valor dentro de una lambda no pueden ser modificadas. Sin embargo, si necesitas modificar las variables capturadas por valor, puedes declarar la lambda como `mutable`:
#include <iostream>
int main() {
int x = 10;
auto incrementa = [x]() mutable {
x++;
std::cout << "Valor dentro de la lambda: " << x << std::endl;
};
incrementa(); // Imprime 11
std::cout << "Valor fuera de la lambda: " << x << std::endl; // Imprime 10
return 0;
}
En este caso, `x` se incrementa dentro de la lambda, pero fuera de ella permanece inalterado.
Las lambdas en C++ son una herramienta poderosa para escribir código más claro y conciso. Facilitan la escritura de funciones pequeñas y de un solo uso y son especialmente útiles cuando se trabaja con funciones de la STL y otras APIs que aceptan funciones como parámetros.