C++ 通过引用传递错误:const boost::system::error\u code&;犯错误

C++ 通过引用传递错误:const boost::system::error\u code&;犯错误,c++,boost,boost-asio,C++,Boost,Boost Asio,我想用自己的错误代码调用完成处理程序,但参数的签名是: const boost::system::error_code& err 我担心我构造的错误代码的生命周期,特别是与异步处理程序、链式处理程序、io_service.post以及对超出范围的基于堆栈的错误代码的引用的不小心传播有关 我可以试试这样的东西: const boost::system::error_code err = boost::system::errc::make_error_code(boost::sy

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

const boost::system::error_code& err
我担心我构造的错误代码的生命周期,特别是与异步处理程序、链式处理程序、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中出错)

这安全吗?无泄漏

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

即使处理程序函数签名采用const ref error_代码,存储错误代码的任何处理程序对象都应存储该代码的副本。如果你不这样做,你(正如你所担心的)最终会在任何事情上遇到生命周期问题,而不是最琐碎的基于asio的程序

默认情况下,C++函数对象实际上是以这种方式运行的——为了让它们存储引用,您必须特意向它们传递reference_包装器,这是有充分理由的。对传递副本的程序进行推理要容易得多。而且在多线程程序中,更频繁地传递拷贝会提供更好的性能,因为不需要担心互斥争用或缓存刷新

此外,
error\u code
对象非常轻量级。它们按值复制比按引用使用更快

总之,不要这样做:

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

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

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

handler(make_error_code(boost::system::errc::bad_message));
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)); 
});
或者这个:

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)); 
});

即使处理程序函数签名采用const ref error_代码,存储错误代码的任何处理程序对象都应存储该代码的副本。如果你不这样做,你(正如你所担心的)最终会在任何事情上遇到生命周期问题,而不是最琐碎的基于asio的程序

默认情况下,C++函数对象实际上是以这种方式运行的——为了让它们存储引用,您必须特意向它们传递reference_包装器,这是有充分理由的。对传递副本的程序进行推理要容易得多。而且在多线程程序中,更频繁地传递拷贝会提供更好的性能,因为不需要担心互斥争用或缓存刷新

此外,
error\u code
对象非常轻量级。它们按值复制比按引用使用更快

总之,不要这样做:

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

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

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

handler(make_error_code(boost::system::errc::bad_message));
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)); 
});
或者这个:

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)); 
});

不要担心传递值。对于一个错误代码来说,它非常便宜。它们被设计成这样通过。我担心的不仅仅是效率。在被引用的实例超出范围之前,按引用传递是正常的。
error\u code
Asio传递给所有用户提供的处理程序都在堆栈上。此外,还值得考虑通过调用处理程序来允许使用自定义调用策略。对于一个错误代码来说,它非常便宜。它们被设计成这样通过。我担心的不仅仅是效率。在被引用的实例超出范围之前,按引用传递是正常的。
error\u code
Asio传递给所有用户提供的处理程序都在堆栈上。此外,可能值得考虑通过调用处理程序来允许使用自定义调用策略;你能帮我保证这不会传递对堆栈上临时实例的引用吗?处理程序(生成错误代码(boost::system::errc::bad_消息));(由于仍然通过引用传递)它可以传递引用,也可以不传递引用,但如果处理程序需要副本,它将立即从引用中获取副本。处理程序对象/函数应存储和转发的唯一引用是输入和输出缓冲区的引用(明确记录asio缓冲区必须超过处理程序对象-我们在构造处理程序时通过将共享的ptr副本传递给缓冲区来实现),感谢全面的回答;你能帮我保证这不会传递对堆栈上临时实例的引用吗?处理程序(生成错误代码(boost::system::errc::bad_消息));(由于仍然通过引用传递)它可以传递引用,也可以不传递引用,但如果处理程序需要副本,它将立即从引用中获取副本。处理程序对象/函数应存储和转发的唯一引用是输入和输出缓冲区的引用(明确记录asio缓冲区必须超过处理程序对象-我们在构造处理程序时通过向缓冲区传递共享的ptr副本来实现)