可以优化按值捕获的 lambda 吗?

Can lambda capture-by-value be optimized out?

本文关键字:lambda 优化      更新时间:2023-10-16

我目前正在为一个项目使用 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. 
    });
}

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

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

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

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