了解 boost::beast 客户端示例 websocket_client_async_ssl.cpp 中的函数参数(按值传递而不是按常量引用传递)
Understand function parameters(pass by value instead of by const reference) in boost::beast client example websocket_client_async_ssl.cpp
参考:
boost_1_78_0/doc/html/boost_asio/reference/ip__basic_resolver/async_resolve/overload1.html
template<
typename ResolveHandler = DEFAULT>
DEDUCED async_resolve(
const query & q,
ResolveHandler && handler = DEFAULT);
The handler to be called when the resolve operation completes. Copies
will be made of the handler as required. The function signature of the
handler must be:
void handler(
const boost::system::error_code& error, // Result of operation.
resolver::results_type results // Resolved endpoints as a range.
);
boost_1_78_0/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp
void run(char const *host, char const *port, char const *text) {
...
resolver_.async_resolve(
host, port,
beast::bind_front_handler(&session::on_resolve, shared_from_this()));
}
void on_resolve(beast::error_code ec, tcp::resolver::results_type results) {
if (ec)
return fail(ec, "resolve");
// Set a timeout on the operation
beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));
// Make the connection on the IP address we get from a lookup
beast::get_lowest_layer(ws_).async_connect(
results,
beast::bind_front_handler(&session::on_connect, shared_from_this()));
}
问题 1> 为什么 on_resolve
使用以下函数签名?
on_resolve(beast::error_code ec, tcp::resolver::results_type results)
如上所示,第一个参数(即ec
)作为传递值。这几乎发生在所有其他将 beast::error_code
作为示例代码中的输入参数的函数中。
而不是
on_resolve(const beast::error_code& ec, tcp::resolver::results_type results)
问题 2> 为什么文档不建议使用以下内容?
on_resolve(const beast::error_code& ec, const tcp::resolver::results_type& results)
谢谢
如果你愿意的话,这是 Asio 和 Beast 之间的文化差异。
UPDATE
There's some contention about my initial response.
It turns out that at least Boost System's error_code
recently got endowed with shiny new (non-standard) features, that makes it bigger. Perhaps big enough to make it more efficient to pass by reference.
In the words of Vinnie Falco: This needs to be studied again.
理由
在Asio中,标准的“学说”是const&取error_code
。在Beast中,标准做法其实是按值传递,也就是IMO,error_code
的本意。
本质上,error_code
只是 (int, error_category const*)
的一个元组,它被简单地复制并因此被优化。按值传递为编译器提供了更多的优化空间,尤其是在内联时。一个关键因素是 value-arguments 从不创造别名机会。
(我可以尝试找到一个参考,因为我认为一些 Beast 开发者已经记录在案解释这个理由。)
为什么可以?
任何通过值获取 T 的函数都是 delegation-compatible,要求 它通过 const 引用获取 T,只要 T 是可复制的。
其他想法
Asio 在过去首选甚至强制执行 error_code const&
可能有历史原因,但据我所知,这些原因中的任何一个都已过时。
参考: boost_1_78_0/doc/html/boost_asio/reference/ip__basic_resolver/async_resolve/overload1.html
template<
typename ResolveHandler = DEFAULT>
DEDUCED async_resolve(
const query & q,
ResolveHandler && handler = DEFAULT);
The handler to be called when the resolve operation completes. Copies will be made of the handler as required. The function signature of the handler must be:
void handler(
const boost::system::error_code& error, // Result of operation.
resolver::results_type results // Resolved endpoints as a range.
);
boost_1_78_0/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp
void run(char const *host, char const *port, char const *text) {
...
resolver_.async_resolve(
host, port,
beast::bind_front_handler(&session::on_resolve, shared_from_this()));
}
void on_resolve(beast::error_code ec, tcp::resolver::results_type results) {
if (ec)
return fail(ec, "resolve");
// Set a timeout on the operation
beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));
// Make the connection on the IP address we get from a lookup
beast::get_lowest_layer(ws_).async_connect(
results,
beast::bind_front_handler(&session::on_connect, shared_from_this()));
}
问题 1> 为什么 on_resolve
使用以下函数签名?
on_resolve(beast::error_code ec, tcp::resolver::results_type results)
如上所示,第一个参数(即ec
)作为传递值。这几乎发生在所有其他将 beast::error_code
作为示例代码中的输入参数的函数中。
而不是
on_resolve(const beast::error_code& ec, tcp::resolver::results_type results)
问题 2> 为什么文档不建议使用以下内容?
on_resolve(const beast::error_code& ec, const tcp::resolver::results_type& results)
谢谢
如果你愿意的话,这是 Asio 和 Beast 之间的文化差异。
UPDATE
There's some contention about my initial response.
It turns out that at least Boost System's
error_code
recently got endowed with shiny new (non-standard) features, that makes it bigger. Perhaps big enough to make it more efficient to pass by reference.In the words of Vinnie Falco: This needs to be studied again.
理由
在Asio中,标准的“学说”是const&取error_code
。在Beast中,标准做法其实是按值传递,也就是IMO,error_code
的本意。
本质上,error_code
只是 (int, error_category const*)
的一个元组,它被简单地复制并因此被优化。按值传递为编译器提供了更多的优化空间,尤其是在内联时。一个关键因素是 value-arguments 从不创造别名机会。
(我可以尝试找到一个参考,因为我认为一些 Beast 开发者已经记录在案解释这个理由。)
为什么可以?
任何通过值获取 T 的函数都是 delegation-compatible,要求 它通过 const 引用获取 T,只要 T 是可复制的。
其他想法
Asio 在过去首选甚至强制执行 error_code const&
可能有历史原因,但据我所知,这些原因中的任何一个都已过时。