Tôi đang tăng cường học tập :: asio và C++ 11 cùng một lúc. Một trong những chương trình thử nghiệm của tôi, đó thực sự là một sự thích nghi của one of the samples given in the boost::asio tutorial như sau:Làm thế nào để viết một hàm ẩn danh/lambda tự chuyển nó thành một cuộc gọi lại?
#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;
}
Khi tôi chạy chương trình này, tôi nhận được một lỗi segmentation. Tôi hiểu tại sao tôi bị lỗi phân đoạn. Sau khi hàm tạo được thực hiện xong, biến số callback
của hàm khởi tạo nằm ngoài phạm vi và biến số callback
của lambda, là tham chiếu đến biến số callback
của hàm tạo, trở thành tham chiếu đáng lơ lửng.
Vì vậy, tôi sửa đổi dòng quan trọng với:
callback = [callback, &](const boost::system::error_code&) { // critical line
Sau đó biên dịch nó, chạy nó, và nhận được một lỗi chức năng gọi xấu. Một lần nữa, tôi hiểu tại sao tôi nhận được lỗi cuộc gọi chức năng xấu. Trong phạm vi lambda, biến số callback
của hàm tạo vẫn chưa được gán bất kỳ giá trị nào, vì vậy nó cho tất cả các mục đích thực tế là một con trỏ hàm lơ lửng. Do đó, biến số callback
của lambda, là một bản sao của biến số callback
của hàm tạo, cũng là một con trỏ hàm lơ lửng.
Sau khi suy nghĩ về vấn đề này trong một thời gian, tôi nhận ra rằng những gì tôi thực sự cần là gọi lại có thể tham khảo để tự sử dụng một con trỏ hàm, không phải là một tham chiếu đến một con trỏ hàm. Các mẫu đạt được điều này bằng cách sử dụng một chức năng được đặt tên như gọi lại, thay vì một ẩn danh. Tuy nhiên, việc chuyển các hàm có tên gọi là callbacks không phải là rất thanh lịch. Có cách nào để có được một chức năng nặc danh có một con trỏ chức năng cho chính nó như là một biến địa phương?
Tôi đã nói rõ ràng rằng tôi hiểu tại sao chương trình của tôi không hoạt động. Tôi muốn biết _how_ một lambda có thể có một con trỏ hàm (chính nó kéo dài mãi mãi) thay vì tham chiếu đến một con trỏ hàm tới chính nó (có thể trở thành tham chiếu lơ lửng khi biến con trỏ hàm thực tế không nằm trong phạm vi). – pyon
OK, tôi nghĩ rằng giải pháp đã phần nào rõ ràng khi tước nó xuống nguyên tắc tại sao nó không hoạt động. Bạn đã thử làm "callback" một thành viên của lớp? –