可以优化lambda值的捕获吗?

Pau*_*ger 2 c++ lambda boost lifetime boost-asio

我目前正在为项目使用boost :: asio,并且必须将缓冲区发送到远程端点.我当前发送数据的算法如下所示:

void send_the_data(DataElement const& data)
{
    auto databuf = make_shared<std::vector<uint8_t>>(data.to_bytes());

    // lambda object holds a reference to the data to prevent early destruction. 
    asio::async_write(this->sock,
        asio::buffer(databuf),
        transfer_all(),
        [this, databuf](size_t bt, boost::system::error_code const& ec)
    {
        if(ec) this->handle_error(ec);
        else this->do_the_next_thing();

        assert(bt = databuf->size());
        // the destructor of this lambda should clean up the data buffer here,
        // after it has been handled. 
    });

}
Run Code Online (Sandbox Code Playgroud)

我的逻辑是,shared_ptr的lambda捕获将阻止它在async_write完成之后被销毁,然后在处理程序执行后正确清理缓冲区.

但是,我很好奇,如果主要编译器或标准允许变量的捕获被忽略,如果在lambda的主体中没有引用它,这将导致未定义的行为(由于可能访问一个在async_write调用中悬空指针),或者如果标准保证不会省略所有值捕获.

Mic*_*zel 5

虽然[expr.prim.lambda]§2理论上允许编译器优化闭包类型,但只允许在as-if规则下进行此类优化.因此,编译器可以优化来自闭包类型的未引用数据,但它仍然必须产生与各个成员的构造/销毁相关联的任何副作用.

[expr.prim.lambda]§10指定对于每个显式捕获,都会创建闭包类型的成员.[expr.prim.lambda]§15指定了它的初始化方式.在此基础上,我会说,一个编译器不会允许优化掉你的shared_ptr.