将 lambda 与自动声明结合使用还是就地使用?
Using lambdas with auto declaration vs in-place?
我正在尝试学习现代 C++,并且我正在使用 Boost.Asio 进行联网。我写了一个TCP连接class,它使用了Asio的异步操作。这是目前我从套接字读取数据的方法:
template<class T>
inline auto connection<T>::read(size_t length) -> void
{
auto handler = [&](const boost::system::error_code& error, size_t bytes_transferred) {
if (error == boost::asio::error::eof or error == boost::asio::error::connection_reset) {
close();
} else {
on_read(bytes_transferred);
}
};
socket.async_read_some(boost::asio::buffer(read_buffer, length), handler);
}
这里我用 auto 单独声明了读取处理程序,因为我认为它看起来比就地 lambda 更具可读性,即
template<class T>
inline auto connection<T>::read(size_t length) -> void
{
socket.async_read_some(boost::asio::buffer(read_buffer, length), [&](const boost::system::error_code& error, size_t bytes_transferred) {
if (error == boost::asio::error::eof or error == boost::asio::error::connection_reset) {
close();
} else {
on_read(bytes_transferred);
}
});
}
但是我 运行 遇到第一个版本的分段错误,我相信这是因为当方法超出范围时处理程序 lambda 丢失。然后我尝试用 std::move
移动处理程序
socket.async_read_some(boost::asio::buffer(read_buffer, length), std::move(handler));
这似乎修复了段错误。
现在我的问题是:使用第一个版本(std::move)与就地使用是否存在任何性能或其他问题?您认为哪一种做法更好?
这两个代码示例都应该有效。第一个示例将处理程序作为左值传递,在这种情况下,实现将制作一个副本。第二个示例将 lambda 作为纯右值传递,在这种情况下,实现将执行移动构造。由于左值和纯右值都是微不足道的,所以这两个操作是相同的。
Networking TS 中的异步启动函数(以及 Asio 和 Boost.Asio 的扩展)通过执行 "decay-copy." 获取处理程序的所有权,这意味着处理程序被复制或移动取决于参数是否为左值。
我不确定为什么您的第一个示例会崩溃,但这与 lambda 的生命周期无关。出于显而易见的原因,异步启动函数从不通过引用接收句柄,并且始终通过衰减复制获得所有权。
你的代码一定有其他问题,在你没有粘贴的部分。例如,在函数 returns?
之后,是什么让连接对象保持活动状态
我正在尝试学习现代 C++,并且我正在使用 Boost.Asio 进行联网。我写了一个TCP连接class,它使用了Asio的异步操作。这是目前我从套接字读取数据的方法:
template<class T>
inline auto connection<T>::read(size_t length) -> void
{
auto handler = [&](const boost::system::error_code& error, size_t bytes_transferred) {
if (error == boost::asio::error::eof or error == boost::asio::error::connection_reset) {
close();
} else {
on_read(bytes_transferred);
}
};
socket.async_read_some(boost::asio::buffer(read_buffer, length), handler);
}
这里我用 auto 单独声明了读取处理程序,因为我认为它看起来比就地 lambda 更具可读性,即
template<class T>
inline auto connection<T>::read(size_t length) -> void
{
socket.async_read_some(boost::asio::buffer(read_buffer, length), [&](const boost::system::error_code& error, size_t bytes_transferred) {
if (error == boost::asio::error::eof or error == boost::asio::error::connection_reset) {
close();
} else {
on_read(bytes_transferred);
}
});
}
但是我 运行 遇到第一个版本的分段错误,我相信这是因为当方法超出范围时处理程序 lambda 丢失。然后我尝试用 std::move
移动处理程序socket.async_read_some(boost::asio::buffer(read_buffer, length), std::move(handler));
这似乎修复了段错误。
现在我的问题是:使用第一个版本(std::move)与就地使用是否存在任何性能或其他问题?您认为哪一种做法更好?
这两个代码示例都应该有效。第一个示例将处理程序作为左值传递,在这种情况下,实现将制作一个副本。第二个示例将 lambda 作为纯右值传递,在这种情况下,实现将执行移动构造。由于左值和纯右值都是微不足道的,所以这两个操作是相同的。
Networking TS 中的异步启动函数(以及 Asio 和 Boost.Asio 的扩展)通过执行 "decay-copy." 获取处理程序的所有权,这意味着处理程序被复制或移动取决于参数是否为左值。
我不确定为什么您的第一个示例会崩溃,但这与 lambda 的生命周期无关。出于显而易见的原因,异步启动函数从不通过引用接收句柄,并且始终通过衰减复制获得所有权。
你的代码一定有其他问题,在你没有粘贴的部分。例如,在函数 returns?
之后,是什么让连接对象保持活动状态