2012-09-28 12 views
28

Estaba leyendo sobre cierres en la red. Me preguntaba si C++ tiene una instalación in-build para cierres o hay alguna manera de implementar cierres en C++.¿Tenemos cierres en C++?

+3

Además de la respuesta siguiente, también consulte http://en.cppreference.com/w/cpp/language/lambda para obtener más información sobre una página de referencia. –

+0

Aparentemente mucha gente todavía mezcla funciones anónimas con cierres. Todavía no está claro para mí si C++ 11 admite cierres, o simplemente funciones anónimas ("lambdas"). No esperaría que C++ admitiera cierres reales en el mismo sentido que en JavaScript, Python, Scala y otros, lo encontraría muy sorprendente. – dividebyzero

+1

Demostrando que estoy equivocado, sí, capta las variables en contexto, por copia e incluso por referencia, aparentemente, la única peculiaridad es que no hay recolección de basura ... Todavía me gustaría entender mejor cómo funciona todo esto en la práctica http: // en.cppreference.com/w/cpp/language/lambda – dividebyzero

Respuesta

6

Sí, C++ 11 tiene cierres nombrados lambdas.

En C++ 03 no hay soporte incorporado para lambdas, pero existe la implementación Boost.Lambda.

5

Sospecho que depende de lo que quiere decir con el cierre. El significado que he usado siempre implica la recolección de basura de algún tipo (aunque creo que podría implementarse utilizando el recuento de referencias); a diferencia de lambdas en otros lenguajes , que capturan referencias y mantienen el objeto referenciado con vida, C++ lambdas captura un valor, o el objeto al que se refiere es no mantenido vivo (y la referencia puede colgarse fácilmente).

12

Si usted entiende el cierre como una referencia a una función que tiene un contexto integrado, persistente, oculto y unseparable (memoria, estado), que sí:

class add_offset { 
private: 
    int offset; 
public: 
    add_offset(int _offset) : offset(_offset) {} 
    int operator() (int x) { return x + offset; } 
} 

// make a closure 
add_offset my_add_3_closure(3); 

// use cloure 
int x = 4; 
int y = my_add_3_closure(x); 
std::cout << y << std::endl; 

la próxima uno modifica su estado:

class summer 
{ 
private: 
    int sum; 
public: 
    summer() : sum(0) {} 
    int operator() (int x) { return sum += x; } 
} 

// make a closure 
summer adder; 
// use closure 
adder(3); 
adder(4); 
std::cout << adder(0) << std::endl; 

No se puede hacer referencia (acceso) al estado interno desde afuera.

Dependiendo de cómo lo defina, un cierre puede contener una referencia a más de una función o dos cierres pueden compartir el mismo contexto, es decir, dos funciones pueden compartir el mismo estado persistente, ...,.

El cierre significa que no contiene variables libres: es comparable a una clase con solo atributos privados y solo método (s) público (s).

+3

El comportamiento es similar a un cierre pero no diría que es un cierre. – Setepenre

+0

@Stepenre ¿cuál sería la diferencia? – Zrin

+2

Esto apenas parece un cierre, lo que tienes aquí es solo un objeto que contiene un estado modificado por un método, más algo de azúcar sintáctico debido a que es "operador()" en lugar de cualquier otro método. Haz que devuelva una lambda que dependa del estado, o de un parámetro del método, y luego estamos hablando. – dividebyzero

6

Sí, muestra cómo podría implementar una función con un estado sin utilizar un funtor.

#include <iostream> 
#include <functional> 


std::function<int()> make_my_closure(int x){ 
    return [x]() mutable { 
     ++x; 
     return x; 
    }; 
} 

int main() 
{ 
    auto my_f = make_my_closure(10); 

    std::cout << my_f() << std::endl; // 11 
    std::cout << my_f() << std::endl; // 12 
    std::cout << my_f() << std::endl; // 13 

    auto my_f1 = make_my_closure(1); 

    std::cout << my_f1() << std::endl; // 2 
    std::cout << my_f1() << std::endl; // 3 
    std::cout << my_f1() << std::endl; // 4 

    std::cout << my_f() << std::endl; // 14 
} 

me olvidó la palabra clave mutable que introdujo un comportamiento indefinido (versión ruido metálico regresaba un valor de basura). Tal como está implementado, el cierre funciona bien (en GCC y clang)

+0

Para estar realmente seguro, sería bueno ver qué pasa si ejecuta 'my_f()' de nuevo después de 'my_f1()', porque aún puede ser la misma variable que acaba de asignar directamente con la llamada a 'make_my_closure '. – dividebyzero

+1

'x' es un valor temporal en' make_my_closure'. Así que IMO no tendría sentido. Agregué el caso que me pidió. Que se comportan como se esperaba – Setepenre