了解 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& 可能有历史原因,但据我所知,这些原因中的任何一个都已过时。