2011-01-13 16 views
31

Me pregunto dónde deberíamos usar lambda expresión sobre el functor en C++. Para mí, estas dos técnicas son básicamente las mismas, incluso el functor es más elegante y más limpio que lambda. Por ejemplo, si quiero reutilizar mi predicado, tengo que copiar la parte lambda una y otra vez. Entonces, ¿cuándo realmente Lambda viene a colocar?Lambda Expresión vs Functor en C++

+1

Por cierto, no sé que pondría "lambda" como código. No es una palabra clave o tipo en C++. Hay algo así como una 'expresión lambda', pero "lambda" no es algo que verías en el código a menos que estuvieras usando la biblioteca lambda de boost o en realidad tuviese algo llamado eso en tu propio código. –

+0

@ Noah Roberts: gracias por señalar eso. Editado! Mi punto era enfatizar la palabra. – Chan

Respuesta

12

1) Es trivial y tratar de compartirlo es más trabajo que beneficio.

2) Definir un functor simplemente agrega complejidad (debido a tener que hacer un montón de variables miembro y basura).

Si ninguna de estas cosas es cierta, entonces tal vez deberías pensar en definir un functor.

Editar: parece ser que necesita un ejemplo de cuándo sería bueno usar una lambda sobre un functor. Aquí van:

typedef std::vector< std::pair<int,std::string> > whatsit_t; 

int find_it(std::string value, whatsit_t const& stuff) 
{ 
    auto fit = std::find_if(stuff.begin(), stuff.end(), [value](whatsit_t::value_type const& vt) -> bool { return vt.second == value; }); 

    if (fit == stuff.end()) throw std::wtf_error(); 

    return fit->first; 
} 

Sin lambdas que tendría que utilizar algo que se construye de manera similar un funtor sobre el terreno o escribir un objeto funtor externamente enlazable para algo que es molesto trivial.

Por cierto, creo que wtf_error es una extensión.

+0

No olvides que abarrotar tu espacio de nombres con clases de functor. –

+2

@Paul Nathan: Eso fue resuelto por espacios de nombres anónimos. –

+0

Roberts: gracias por un buen ejemplo de uso de Lamda. – Chan

0

Como ha señalado, funciona mejor cuando necesita una sola vez y la sobrecarga de codificación de escribirla como una función no vale la pena.

+0

gracias por su rápida respuesta. Pero no entiendo cuál fue la motivación para inventar 'lamda', ya que creo que es más difícil de leer y además no es reutilizable. Tampoco tiene nombre, por lo que el código de lectura requiere mucho más tiempo. – Chan

+0

@ Chan: Herb Sutter fue uno de los defensores más vocales de lambdas. Publicó algunas charlas sobre ellos: http://herbsutter.com/2010/10/30/pdc-languages-panel-andshortened-lambdas-talk/. No los he visto yo mismo, pero sin duda le dirán para qué * él * piensa que son buenos, y darán algunos ejemplos de cuándo los usaría. –

+0

@Steve Jessop: gracias por el enlace. Lo veré. – Chan

14

Una expresión lambda crea un functor sin nombre, es azúcar sintáctica.

Así que lo usa principalmente si hace que su código se vea mejor. Eso generalmente ocurriría si (a) no vas a reutilizar el funtor, o (b) vas a reutilizarlo, pero de un código tan totalmente relacionado con el código actual que para compartirlo básicamente terminan creando my_favourite_two_line_functors.h, y tienen archivos dispares que dependen de él.

Más o menos las mismas condiciones bajo las cuales escribiría cualquier línea (s) de código, y no abstraería ese bloque de código en una función.

Dicho esto, con sentencias range-for en C++ 0x, hay algunos lugares en los que habría usado un functor antes, donde podría hacer que su código se vea mejor ahora para escribir el código como un cuerpo de bucle, no un functor o un lambda.

8

Pequeñas funciones que no se repiten.

La principal queja acerca de los funtores es que no están en el mismo lugar en que fueron utilizados. Por lo tanto, tenía que buscar y leer el functor fuera de contexto en el lugar en el que se estaba utilizando (incluso si solo se estaba utilizando en un lugar).

El otro problema era que el functor necesitaba un cableado para obtener los parámetros en el objeto del functor. No es complejo, pero todo el código repetitivo básico. Y la placa de la caldera es susceptible a problemas de corte y pegado.

Lambda intente y corrija ambos. Pero usaría funtores si la función se repite en múltiples lugares o es más pequeña que (no puedo imaginar un término apropiado, ya que será sensible al contexto) pequeña.

10

Lambdas son básicamente solo azúcares sintácticos que implementan funtores (NB: los cierres no son simples.) En C++ 0x, puede usar la palabra clave auto para almacenar localmente lambdas, y std :: function le permitirá almacenar lambdas o pasarlos de una manera segura.

Mira la Wikipedia article on C++0x.

0

Conceptualmente, la decisión de cuál usar es impulsado por el mismo criterio que el uso de una variable llamada frente a una expresión en el lugar o constante ...

size_t length = strlen(x) + sizeof(y) + z++ + strlen('\0'); 
... 
allocate(length); 
std::cout << length; 

. ..aquí, la creación de una variable de longitud alienta al programa a considerar su corrección y significado de forma aislada de su uso posterior. El nombre del nombre transmite lo suficiente como para que pueda entenderse intuitivamente e independientemente de su valor inicial. Luego permite que el valor se use varias veces sin repetir la expresión (mientras que el manejo de z es diferente). Mientras está aquí ...

allocate(strlen(x) + sizeof(y) + z++ + strlen('\0')); 

... el código total se reduce y el valor se localiza en el punto que se necesita. Lo único que se puede "llevar adelante" de una lectura de esta línea son los efectos secundarios de la asignación y el incremento (z), pero no hay una variable local adicional con alcance o uso posterior que deba tenerse en cuenta. El programador tiene que hacer malabares mentalmente con menos estado mientras continúa su análisis del código.

La misma distinción se aplica a las funciones frente a las declaraciones en línea. Para los propósitos de responder a su pregunta, los funtores contra lambdas pueden verse como un caso particular de esta función versus una decisión preliminar.