gpt4 book ai didi

c++ - 如何编写将自身作为回调传递的匿名函数/lambda?

转载 作者:可可西里 更新时间:2023-11-01 18:16:26 26 4
gpt4 key购买 nike

我正在同时学习 boost::asio 和 C++11。我的一个测试程序,实际上是对 one of the samples given in the boost::asio tutorial 的改编是以下内容:

#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;
}

当我运行这个程序时,我遇到了一个段错误。我确实理解为什么会出现段错误。构造函数完成运行后,构造函数的 callback 变量超出范围,lambda 的 callback 变量,它是对构造函数的 callback 的引用> 变量,成为悬空引用。

所以我修改了关键行:

        callback = [callback, &](const boost::system::error_code&) { // critical line

然后编译,运行,得到一个bad function call错误。再一次,我明白为什么我会收到错误的函数调用错误。在 lambda 范围内,构造函数的 callback 变量仍未分配任何值,因此对于所有实际用途而言,它是一个悬空函数指针。因此,lambda 的 callback 变量(它是构造函数的 callback 变量的拷贝)也是一个悬空函数指针。


思考这个问题一段时间后,我意识到我真正需要的是回调能够引用自身使用函数指针,而不是对函数指针的引用。该示例通过使用命名函数作为回调而不是匿名函数来实现这一点。但是,将命名函数作为回调传递并不是很优雅。有什么方法可以让匿名函数有一个指向自身的函数指针作为局部变量?

最佳答案

有几种选择:

  • 停止使用 lambda。您不必将它们用于一切,您知道。它们涵盖了很多情况,但并未涵盖所有情况。只需使用常规的旧仿函数即可。
  • 让 lambda 存储一个智能指针,指向存储 lambda 的动态分配的 std::function。例如:

    auto pCallback = std::make_shared<std::function<void(const boost::system::error_code&)>>();
    auto 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(pCallback.get());
    }
    };
    *pCallback = callback;

关于c++ - 如何编写将自身作为回调传递的匿名函数/lambda?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8499847/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com