将封装为shared_ptr的Socket传入方法时,Boost.Beast tcp_stream触发删除函数错误
问题分析与解决:Boost.Asio+Beast编译错误(use of deleted function)
问题场景
使用Boost.Asio开发网络程序时,编写了如下代码:
void connections::start_acceptor(){ auto socket=std::make_shared<boost::asio::ip::tcp::socket>(ioc); con_acceptor.async_accept(*socket,[this,socket](const boost::system::error_code ec){ if(!ec){ this->status=true; if(socket->is_open()){ cout<<"client connection Acknoledged with ip - "<<socket->remote_endpoint()<<endl; boost::asio::spawn(con_acceptor.get_executor(), [this,socket](boost::asio::yield_context yield) { r_w_handler(socket, yield); }); }; this->start_acceptor(); } else{ cout<<"Error Accepting - "<<ec.message()<<endl; this->status=false; this->start_listener(); } }); }; void connections::r_w_handler(std::shared_ptr<boost::asio::ip::tcp::socket> socket, boost::asio::yield_context yield) { boost::beast::tcp_stream stream_socket(*socket); try { char data[128]; for (;;) { // std::size_t length = socket->async_read_some(boost::asio::buffer(data), yield); // boost::asio::async_write(*socket, boost::asio::buffer(data, length), yield); } } catch (const std::exception& e) { std::cerr <<" Error with session " << e.what() << std::endl; } };
编译时触发错误:
error: use of deleted function
boost::asio::basic_stream_socket<Protocol, Executor>::basic_stream_socket(const boost::asio::basic_stream_socket<Protocol, Executor>&) [with Protocol = boost::asio::ip::tcp; Executor = boost::asio::any_io_executor]
原因分析
错误核心是**boost::asio::ip::tcp::socket是不可拷贝类型**,其拷贝构造函数被显式删除。
代码中boost::beast::tcp_stream stream_socket(*socket);这一行,试图通过拷贝*socket(原始socket对象)初始化tcp_stream,但tcp_stream的构造函数接收socket对象时会尝试拷贝,而socket不允许拷贝,因此触发编译错误。
解决方法
有两种可行的解决方式:
方式一:移交socket所有权给tcp_stream
用std::move转移socket的所有权,避免拷贝操作。修改r_w_handler中的初始化代码:
// 转移socket所有权给tcp_stream boost::beast::tcp_stream stream_socket(std::move(*socket));
注意:所有权移交后,原shared_ptr<socket>指向的对象会失效,后续不能再通过该shared_ptr操作socket。
方式二:让tcp_stream共享底层套接字资源
若需保留原socket的使用,可通过socket的执行器和原生句柄构造tcp_stream:
boost::beast::tcp_stream stream_socket(socket->get_executor()); stream_socket.assign(socket->native_handle());
这种方式下,tcp_stream与原socket共享底层套接字,需注意避免双重关闭或操作冲突。
推荐优先使用方式一,契合Boost.Beast的设计理念:让tcp_stream接管套接字生命周期,更好地利用其资源管理机制。
内容的提问来源于stack exchange,提问作者aj_codes
相关产品推荐
相关产品推荐

