Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize Boost shared_ptr in constructor

I have a class, which has aboost::asio::io_service object. I want this object stored in a boost::shared_ptr.

So my header looks like this ( I got rid of any unnecessary code so it doesn't distract )

class CommandDispatcher
{
private:
    boost::shared_ptr<boost::asio::io_service> m_ioservice;
public:
    CommandDispatcher();
};

When I now create an object of CommandDispatcherI want that an io_service object to be initialized for the pointer. Now I'm not quite sure how to do this. I looked up two differentsolutions but only one is working and I'm not quite sure if it's a nice one. But see for yourself:

CommandDispatcher::CommandDispatcher()
{
    m_ioservice.reset(new boost::asio::io_service);            // this actually works
    //m_ioservice = boost::make_shared<boost::asio::io_service>
    //    (new boost::asio::io_service);                     // this doesn't work
}

So the reset call is working, but I think this one is actually to reassign the pointer. So it is not wrong to use it but it doesn't seem like the nicest solution to me. The suggestion for the make_shared call I found in another question. But this one just won't work for me ( I implemented it as described in the official boost example ). I get

/usr/local/include/boost/smart_ptr/make_shared.hpp:189: error: invalid conversion from ‘boost::asio::io_service*’ to ‘size_t’

/usr/local/include/boost/smart_ptr/make_shared.hpp:189: error: initializing argument 1 of ‘boost::asio::io_service::io_service(size_t)’

I'm not quite sure how to do this now, which would be the best way ( maybe there is a complete other option to do it ). Or maybe I'm doin it right, but I'm gettin something with the io_servicewrong.

Hope this question hasn't been already here in this way ( I looked up some old question, but no answer seemed to fit for me ).

like image 831
Toby Avatar asked Feb 06 '12 14:02

Toby


3 Answers

If you're using make_shared, then you don't use new yourself; you pass it the constructor arguments, and it will create the object for you. In this case, there are not arguments, so just do:

m_ioservice = boost::make_shared<boost::asio::io_service>();

although it would be nicer to initialise it in the initialiser list rather than the constructor body:

CommandDispatcher::CommandDispatcher() : 
    m_ioservice(boost::make_shared<boost::asio::io_service>())
{
}

Using make_shared has the advantage that it will only perform a single memory allocation, while initialisation using new boost::asio::io_service will require two (one for the object, and one for the shared reference count).

like image 173
Mike Seymour Avatar answered Oct 10 '22 21:10

Mike Seymour


CommandDispatcher::CommandDispatcher()
   : m_ioservice(new boost::asio::io_service) // ver 1. this is how you should do it.
{
    //m_ioservice.reset(new boost::asio::io_service); // ver 2    
    //m_ioservice = boost::make_shared<boost::asio::io_service>(); // ver 3
}
like image 45
ronag Avatar answered Oct 10 '22 19:10

ronag


The nice way is probably

CommandDispatcher::CommandDispatcher() : 
  m_ioservice(new boost::asio::io_service)
{
}

because the alternative has you default-constructing the shared_ptr first, and then reassigning it.

Or, equivalently using make_shared:

CommandDispatcher::CommandDispatcher() : 
  m_ioservice(boost::make_shared<boost::asio::io_service>())
{
}
like image 20
Useless Avatar answered Oct 10 '22 21:10

Useless