通过引用传递错误:const boost :: system :: error_code& ERR

时间:2016-03-08 10:31:28

标签: c++ boost boost-asio

我想用自己的错误代码调用一个完成处理程序,但参数的签名是:

const boost::system::error_code& err

我担心我构造的error_code的生命周期,特别是与异步处理程序,链式处理程序,io_service.post以及对基于堆栈的错误代码的引用的粗心传播有关。范围。

我可以尝试这样的事情:

const boost::system::error_code err = 
    boost::system::errc::make_error_code(boost::system::errc::bad_message);
handler(&err);

但似乎有点可怕不通过价值;特别是如果我想使用io_service.post

使用lambdas是最好的方法吗? (我也可以在lambda中犯错误)

const boost::system::error_code err = 
    boost::system::errc::make_error_code(boost::system::errc::bad_message);
io_service.post([error](){ handler(&err); }

这样安全吗?无泄漏?

handler(boost::system::errc::make_error_code(boost::system::errc::bad_message));

1 个答案:

答案 0 :(得分:5)

即使处理函数签名采用const ref error_code,任何存储错误代码的处理程序对象都应该存储它的副本。如果你不这样做,你会(因为你担心)最终会遇到除了最基本的基于asio的程序以外的任何问题。

默认情况下,C ++函数对象实际上以这种方式运行 - 您必须故意将它们传递给reference_wrappers以使它们存储引用,并且有充分的理由。关于传递副本的程序更容易推理。在多线程程序中,经常传递副本会提供更好的性能,因为没有互斥争用或缓存刷新需要担心。

此外,error_code个对象轻量级。按价值复制比按参考使用更快。

因此,总而言之,不要这样做:

const boost::system::error_code err = 
  boost::system::errc::make_error_code(boost::system::errc::bad_message);
handler(&err);

这样做:

handler(make_error_code(boost::system::errc::bad_message));
不要这样做:

const boost::system::error_code err = 
boost::system::errc::make_error_code(boost::system::errc::bad_message);
io_service.post([error](){ handler(&err); }

这样做:

auto err = make_error_code(boost::system::errc::bad_message);
io_service.post([err](){ handler(err); }

或者这个:

io_service.post(std::bind(hander, make_error_code(boost::system::errc::bad_message));

或者这个:

io_service.post([] {
    handler(make_error_code(boost::system::errc::bad_message)); 
});