Sockets asio反应堆内lambda使用auto与typedef的对比

Sockets asio反应堆内lambda使用auto与typedef的对比,sockets,c++11,lambda,boost-asio,Sockets,C++11,Lambda,Boost Asio,我有一些这样的代码: typedef std::function<void (void)> const& basic_callback_t; void Receive::async_basic(fragmenting_socket& socket, const ID id, basic_callback_t fn) { int buffer[1024]; socket.async_receive(buffer, sizeof(buffer), [&](con

我有一些这样的代码:

typedef std::function<void (void)> const& basic_callback_t;

void Receive::async_basic(fragmenting_socket& socket, const ID id, basic_callback_t fn)
{
int buffer[1024];
socket.async_receive(buffer, sizeof(buffer), [&](const boost::system::error_code& ec, size_t bytes)
{
    ....

    if (fn) 
    {
        fn(); 
    } else
    {
        THROW("async_receive callback: Could not call fn()");
    }
});

}
上面的代码似乎工作正常,
f
gets被调用,finished被设置为true。但是,如果我将匿名lambda传递到
async_basic
或声明
f

auto f = [&] () ....
然后asio反应器将
fn
内部
async\u receive
视为超出范围,并调用
THROW()
语句。有人知道为什么会这样吗?实际上,我不明白为什么专门声明
f
protocol::basic\u callback\u t
有效而声明为
auto
无效。在这两种情况下,函子都放在堆栈上,并且应该在运行
m_服务
的线程中超出范围

我正在使用g++4.8.2编译,其中设置了-std=c++11标志集和-fPIC

干杯
Ben

在这两种变体中

async\u receive
的调用通过引用捕获
fn
。但是,只要
async\u basic
返回,该引用就会失效

这同样适用于
缓冲区[]
事实上:
缓冲区
超出范围,因此在
异步接收
写入时有未定义的行为


UB的本质是任何事情都有可能发生,这解释了为什么您会看到不同的行为。

那么我如何将fn放在堆中,使其不超出范围?谢谢b通常的模式是从这个类中获得一个表示连接/传输顺序的
启用\u共享\u。然后,该类可以拥有缓冲区(以及其他类似state的东西)。对于完成处理程序,您不需要做特殊的事情,只需要不通过引用捕获
函数
,谢谢您的帮助。你能给我举个例子吗?我在这里查找了enable_shared_,这是传递类的shared_ptr的一种方法。我想最安全的方法是创建一个函子,而不是lambda,在堆上创建一个函子,并将其传递给其他人……我的许多答案都说明了这一点。事实上,我在年的最新回答中也进行了非常类似的讨论和讨论。这里有一个搜索让你开始:谢谢。我是通过socket.async\u receive(buffer,sizeof(buffer),[&buffer,id,fn](const boost::system::error\u code&ec,size\u t bytes)获得的{….我通过值传递了std::函数,它成功了。缓冲区仍然不正确,但至少它不是一个拦截器。奇怪的是,认为每个lambda闭包都需要智能指针和小心地通过值传递,而不是通过引用传递,以保持正确性。
auto f = [&] () ....
void Receive::async_basic(fragmenting_socket& socket, const ID id, basic_callback_t fn)
{
    int buffer[1024];
    socket.async_receive(buffer, sizeof(buffer), [&](const boost::system::error_code& ec, size_t bytes)
    {
        if (fn) {
            fn(); 
        } else {
            THROW("async_receive callback: Could not call fn()");
        }
});