Estoy aprendiendo boost :: asio y C++ 11 simultáneamente. Uno de mis programas de prueba, que en realidad es una adaptación de one of the samples given in the boost::asio tutorial es la siguiente:¿Cómo escribir una función/lambda anónima que se pase a sí misma como una devolución de llamada?
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
class printer {
// Static data members
private:
const static boost::posix_time::seconds one_second;
// Instance data members
private:
boost::asio::deadline_timer timer;
int count;
// Public members
public:
printer(boost::asio::io_service& io)
: timer(io, one_second), count(0) {
std::function<void(const boost::system::error_code&)> callback;
callback = [&](const boost::system::error_code&) { // critical line
if (count < 5) {
std::cout << "Current count is " << count++ << std::endl;
timer.expires_at(timer.expires_at() + one_second);
timer.async_wait(callback);
}
};
timer.async_wait(callback);
}
~printer() {
std::cout << "Final count is " << count << std::endl;
}
};
const boost::posix_time::seconds printer::one_second(1);
int main() {
boost::asio::io_service io;
printer p(io);
io.run();
return 0;
}
Cuando ejecuto este programa, aparece un fallo de segmentación. Entiendo por qué obtengo la falla de segmentación. Una vez que el constructor termina de ejecutarse, la variable callback
del constructor queda fuera del alcance, y la variable callback
de lambda, que es una referencia a la variable callback
del constructor, se convierte en una referencia colgante.
Así que modificar la línea crítica con:
callback = [callback, &](const boost::system::error_code&) { // critical line
compilarlos a continuación, ejecutarlo, y obtiene un error de llamada a la función malo. De nuevo, entiendo por qué obtengo el error de llamada a la función incorrecta. Dentro del alcance de lambda, la variable callback
del constructor aún no tiene ningún valor asignado, por lo que para todos los propósitos prácticos es un puntero de función colgante. Por lo tanto, la variable callback
de lambda, que es una copia de la variable callback
del constructor, también es un puntero de función colgante.
Después de pensar en este problema por un tiempo, me di cuenta de que lo que realmente necesita es que la devolución de llamada sea capaz de referirse a sí usando un puntero de función, no una referencia a un puntero de función. La muestra logró esto utilizando una función nombrada como devolución de llamada, en lugar de una función anónima. Sin embargo, pasar funciones nombradas como devoluciones de llamada no es muy elegante. ¿Hay alguna manera de obtener una función anónima tener un puntero a la función como una variable local?
He declarado muy claramente que entiendo por qué mi programa no funciona. Quiero saber cómo una lambda podría tener un puntero de función a sí mismo (que dura para siempre) en lugar de una referencia a un puntero de función a sí mismo (que podría convertirse en una referencia colgante una vez que la variable del puntero a la función salga del alcance). – pyon
Bien, pensé que la solución era algo clara al desvincularla del principio de por qué no funciona. ¿Has intentado hacer "devolución de llamada" a un miembro de la clase? –