可以优化 lambda 按值捕获吗?
Can lambda capture-by-value be optimized out?
我目前正在使用 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 规则 下才允许。因此,编译器可以从闭包类型中优化掉未引用的数据,但它仍然会产生与各个成员的 construction/destruction 相关的任何副作用。
[expr.prim.lambda] §10 specifies that for each explicit capture, a member of the closure type is created. [expr.prim.lambda] §15 指定它是如何初始化的。基于此,我会说编译器 不允许 优化你的 shared_ptr
。
我目前正在使用 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 规则 下才允许。因此,编译器可以从闭包类型中优化掉未引用的数据,但它仍然会产生与各个成员的 construction/destruction 相关的任何副作用。
[expr.prim.lambda] §10 specifies that for each explicit capture, a member of the closure type is created. [expr.prim.lambda] §15 指定它是如何初始化的。基于此,我会说编译器 不允许 优化你的 shared_ptr
。