I'm learning boost: asio e C++ 11 contemporaneamente. Uno dei miei programmi di test, che è in realtà un adattamento del one of the samples given in the boost::asio tutorial è il seguente:Come scrivere una funzione anonima/lambda che si passa come una richiamata?
#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;
}
Quando ho eseguito questo programma, ottengo un errore di segmentazione. Capisco perché ottengo il difetto di segmentazione. Dopo che il costruttore è stato eseguito, la variabile callback
del costruttore non è inclusa e la variabile callback
lambda, che è un riferimento alla variabile callback
del costruttore, diventa un riferimento ciondolante.
Così ho modificare la riga critico con:
callback = [callback, &](const boost::system::error_code&) { // critical line
quindi compilarlo, eseguirlo, e ottenere un errore di funzione di chiamata di male. Ancora una volta, capisco perché ottengo l'errore di chiamata di funzione cattiva. Nell'ambito di lambda, la variabile callback
del costruttore non ha ancora ricevuto alcun valore, quindi per tutti gli scopi pratici è un puntatore a funzione penzolante. Quindi, la variabile callback
di lambda, che è una copia della variabile callback
del costruttore, è anche un puntatore a funzione pendente.
Dopo aver riflettuto su questo problema per un po ', mi sono reso conto che quello che ho veramente bisogno è che il richiamo sia in grado di riferirsi a se stesso usando un puntatore a funzione, non un riferimento a un puntatore a funzione. L'esempio ha ottenuto questo risultato utilizzando una funzione denominata come callback, anziché anonimo. Tuttavia, il passaggio di funzioni con nome come callback non è molto elegante. C'è un modo per ottenere una funzione anonima avere un puntatore a funzione di se stesso come una variabile locale?
Ho detto molto chiaramente che capisco perché il mio programma non funziona. Voglio sapere _come_ un lambda potrebbe avere un puntatore a funzione di se stesso (che dura per sempre) invece di un riferimento a un puntatore di funzione a se stesso (che potrebbe diventare un riferimento ciondolante una volta che la variabile puntatore di funzione effettiva non rientra nell'ambito). – pyon
OK, pensavo che la soluzione fosse piuttosto chiara quando si riduceva al principio del perché non funziona. Hai provato a rendere "callback" un membro della classe? –