2010-02-28 10 views
11

Veo que los objetos de función se usan a menudo junto con los algoritmos STL. ¿Los objetos funcionales surgieron debido a estos algoritmos? ¿Cuándo usas un objeto de función en C++? ¿Cuáles son sus beneficios?¿Cuándo usas los objetos de función en C++?

+0

Ver también: http://stackoverflow.com/questions/356950/c-functors-and-their-uses –

Respuesta

9

Como dice jdv, se utilizan funtores en lugar de punteros a funciones, que son más difíciles de optimizar y en línea para el compilador; además, una ventaja fundamental de los funtores es que pueden preservar fácilmente un estado entre llamadas a ellos , por lo que pueden funcionar de manera diferente dependiendo de las otras veces que se han llamado, realizar un seguimiento de alguna manera de los parámetros que han utilizado, .. .

Por ejemplo, si desea sumar todos los elementos en dos contenedores de enteros que puede hacer algo como esto:

struct 
{ 
    int sum; 
    void operator()(int element) { sum+=element; } 
} functor; 
functor.sum=0; 
functor = std::for_each(your_first_container.begin(), your_first_container.end(), functor); 
functor = std::for_each(your_second_container.begin(), your_second_container.end(), functor); 
std::cout<<"The sum of all the elements is: "<<functor.sum<<std::endl; 

  1. en realidad, como R Samuel Klatchko señala más adelante, pueden soportar múltiples estadísticas independientes es, uno para cada instancia de functor:
    Una declaración un poco más precisa es que los funtores pueden admitir múltiples estados independientes (las funciones pueden admitir un único estado vía estática/globales que no es ni subprocesable ni reentrante).
    Functors le permite utilizar estados aún más complicados, por ejemplo, un estado compartido (campos estáticos) y un estado privado (campos de instancia). Sin embargo, esta flexibilidad adicional rara vez se usa.
+2

Una declaración un poco más precisa es que los funtores pueden admitir múltiples estados independientes (las funciones pueden admitir un solo estado a través de estáticas/globales, que no es ni thread-safe ni reentrant). –

+0

Seguramente quiere decir que los punteros a función son más difíciles de optimizar y en línea? La forma en que está escrito ahora, no está claro. – jalf

+0

Quise decir que los punteros a las funciones son más difíciles de optimizar y en línea; no me parece que no esté claro, "eso" se refiere a la última frase de la oración anterior, es decir, "punteros de función". Sin embargo, si desea sugerir una fraseología mejor, me complacerá editarla. :) –

2

Los objetos de función se diseñaron para permitir una fuerte capa de abstracción sobre STL, y en ese aspecto son geniales.

Sin embargo, yo prefiero usar boost::bind y enlazar una función para los algoritmos de STL lugar - por lo general (aunque no en los casos en que el objeto tiene un estado) que parece una solución más elegante.

std::for_each(callback.begin(), callback.end(), 
    boost::bind(&Callback::call(),_1) 
); 

También, otra alternativa próximo son de lambda en C++ 0x (ejemplo robado sin vergüenza de Wikipedia):

std::vector<int> someList; 
int total = 0; 
std::for_each(someList.begin(), someList.end(), [&total](int x) { 
    total += x; 
}); 
std::cout << total; 

en cuenta que debido a los cierres, que hacer no tiene la restricción de bind acerca de no tener un estado.

8

Los objetos de función (funtores) se utilizan generalmente en lugar de punteros a funciones. Los punteros de función tienen el problema de que el compilador los pasa típicamente como punteros crudos, lo que dificulta al compilador alinear el código más tarde. Y son más fáciles de dar parámetros.

+0

+1 - Para la mención que se detalla –

+0

Así que supongo que los funtores se usan más por su eficiencia ... – jasonline

+0

@jasonline: Esa no es la única ventaja, pero en muchos casos es la principal ventaja. –

1

No puedo decir por qué surgieron, ¡posiblemente porque podían!

¿Cuándo utilizas un functor? Considere que un functor solo está moviendo el código que normalmente pondría en un bucle en el operador() de una clase, no son muy diferentes de simplemente llamar a una función en un ciclo while ... excepto, al usarlos le permite al compilador alinear el código y también puede pasar un objeto preconstruido que haya construido con algún estado. Este último punto los hace muy poderosos.

Compare el algoritmo de ordenamiento con la llamada qsort de CRT. Hacen lo mismo, solo que lo hacen de manera diferente.

2

Un objeto de función es una función que también es un objeto, es decir, tiene estado.Las funciones normales generalmente no tienen estado. Pueden emular tener estado al acceder a variables globales, pero luego el estado se comparte en todas las invocaciones.

2

La idea de encapsular una función como un objeto se remonta a Lisp y Smalltalk. La idea de C++ de functor fue un capítulo en el libro de Jim Coplien Advanced C++ Programming Styles and Idioms en 1991. STL utilizó el modismo y lo popularizó aún más.

1

This article tiene una gran visión en profundidad de los objetos de función, y cómo puede hacer que el código sea mucho más potente y más limpio también.

Cuestiones relacionadas