C++ Boost Asio-使用共享ptr处理解析器和套接字

C++ Boost Asio-使用共享ptr处理解析器和套接字,c++,sockets,boost,boost-asio,shared-ptr,C++,Sockets,Boost,Boost Asio,Shared Ptr,我有一个类可以通过TCP发送消息。这里是简化的界面: class CommandScreenshot : public CameraCommand { public: CommandScreenshot(); ~CommandScreenshot(); void Dispatch(boost::shared_ptr<boost::asio::io_service> io_service); private: void resolve_handle

我有一个类可以通过TCP发送消息。这里是简化的界面:

class CommandScreenshot : public CameraCommand
{
public:
    CommandScreenshot();
    ~CommandScreenshot();
    void Dispatch(boost::shared_ptr<boost::asio::io_service> io_service);

 private:
     void resolve_handler(const boost::system::error_code& err,
          boost::asio::ip::tcp::resolver::iterator endpoint_iterator);

};
其他所有操作都将在以下回调函数中完成。
io_服务
对象以及相应的线程由另一个类管理(它有一个
CommandScreenshot
实例并调用
Dispatch
函数)

现在,要使用Boost实现一个简单的TCP连接,您需要一个
解析器
和一个
套接字
对象,这两个对象都绑定到
io_服务
对象。由于此时只传递
io\u服务
对象,因此调用函数,我无法在类构造函数中初始化它们。 另外,不可能将它们声明为类成员,然后在函数本身中初始化它们

我的第一个想法是在函数调用时初始化它们,并将它们传递给我的完成处理程序。这意味着每次调用函数时我都会声明这两个对象,并将它们绑定到
io\u服务
。然后在
async\u resolve
中,我通过
boost::bind
添加这两个参数。这意味着我的
resolve\u处理程序将需要更多参数,例如:

void resolve_handler(const boost::system::error_code& err,
          boost::asio::ip::tcp::resolver::iterator endpoint_iterator,
          boost::asio::ip::tcp::resolver resolver,
          boost::asio::ip::tcp::socket socket);
我实际上怀疑这是一个体面和公平的解决办法。通常,这些对象应该作为成员保留,而不是被复制——因此我又重新考虑了一下,然后我想到了
boost::shared\u ptr

在我的标题中,它现在看起来如下所示:

// Stuff above stays the same
private:
  boost::shared_ptr<boost::asio::ip::tcp::resolver> m_resolver;
  boost::shared_ptr<boost::asio::ip::tcp::socket> m_socket;
// Stuff below stays the same
//以上内容保持不变
私人:
boost::共享\u ptr m\u解析器;
boost::共享\u ptr m_套接字;
//下面的内容保持不变
其实施将是:

void CommandScreenshot::Dispatch(boost::shared_ptr<boost::asio::io_service> io_service)
{
    m_resolver.reset(new boost::asio::ip::tcp::resolver(*io_service));
    m_socket.reset(new boost::asio::ip::tcp::socket(*io_service));
    boost::asio::ip::tcp::resolver::query query(m_hostname,"http");
    m_resolver->async_resolve(query,boost::bind(&CommandScreenshot::resolve_handler,this,boost::asio::placeholders::error, boost::asio::placeholders::iterator));
    return;
}
void命令截图::调度(boost::共享的ptr io_服务)
{
重置(新的boost::asio::ip::tcp::resolver(*io_服务));
重置(新的boost::asio::ip::tcp::socket(*io_服务));
boost::asio::ip::tcp::解析器::查询查询(m_主机名,“http”);
m_解析器->异步解析(查询,boost::bind(&CommandScreenshot::resolve_处理程序,this,boost::asio::placeholders::error,boost::asio::placeholders::iterator));
返回;
}
这样,我就不需要复制4个(甚至更多)参数并将它们绑定在一起。当我需要套接字对象时,我可以通过指针(类成员)访问它

现在我的简单问题是->这是正确的方法吗?即使异步部分尚未完成,也可以多次调用该函数。(我知道我应该用互斥锁保护套接字和解析器)。但是每次调用
Dispatch
函数时,我都会创建一个新对象,这是否干净呢?
reset
调用是否足以消除任何不需要的内存


我知道这是一个很长的文本,用于一个特别的短问题,而且甚至没有一个错误。但我总是想知道这是否是一种体面的方式,如果有更好的方式,我会怎么做。

将memebers定义为asio对象的共享的想法是可以的。但您不应该每次都破坏和创建它们:

if (!m_resolver)
{
  m_resolver.reset(...);
}
此外,如果确保asio对象上的所有操作都发生在运行io_服务的线程中(假设每个io_服务只有一个线程),则可以避免显式锁定。为此,只需分离接口函数的实现并使用post()。当然,使用shared_from_这个成语可以简化对象生命周期控制:

void CommandScreenshot::someMethod(Arg1 arg1, Arg2 arg2)            
{
  io_.post(bind(&CommandScreenshot::someMethodImpl, shared_from_this, arg1, arg2)); 
}
//...
void CommandScreenshot::someMethodImpl(Arg1 arg1, Arg2 arg2)            
{
  // do anything you want with m_resolver, m_socket etc.
}
void CommandScreenshot::someMethod(Arg1 arg1, Arg2 arg2)            
{
  io_.post(bind(&CommandScreenshot::someMethodImpl, shared_from_this, arg1, arg2)); 
}
//...
void CommandScreenshot::someMethodImpl(Arg1 arg1, Arg2 arg2)            
{
  // do anything you want with m_resolver, m_socket etc.
}