boost shared_from_this<>()

99封情书 提交于 2019-12-03 03:07:59

The biggest "gotcha" I've run into is that it's illegal to call shared_from_this from the constructor. This follows directly from the rule that a shared_ptr to the object must exist before you can call shared_from_this.

From my understanding, sometimes in your code you want a class to offer up shared_ptr's to itself so that other parts of your code can obtain shared_ptr's to an object of your class after it has been constructed.

The problem is that if your class just has a shared_ptr<> to itself as a member variable, it will never get automatically destructed, since there is always "one last reference" hanging around to itself. Inheriting from enable_shared_from_this gives your class an automatic method which not only returns a shared_ptr, but only holds a weak shared pointer as a member variable so as not to affect the reference count. This way, your class will be freed as usual when the last reference to it is gone.

I've never used it, but this is my understanding of how it works.

shared_from_this<> is used if an object wants to get access to a shared_ptr<> pointing to itself.

Usually an object only knows about the implicit this pointer, but not about any shared_ptr<> managing it. Also, this cannot easily be converted into a shared_ptr<> that shares ownership with other existing shared_ptr<> instances, so there is no easy way for an object to get a valid shared_ptr<> to itself.

shared_from_this<> can be used to solve this problem. For example:

struct A : boost::enable_shared_from_this<A> {
   server *io;
   // ...

   void register_self() {
      io->add_client(shared_from_this());
   }
};

the boost::asio::io_service destructor documentation explains it fairly well

The destruction sequence described above permits programs to simplify their resource management by using shared_ptr<>. Where an object's lifetime is tied to the lifetime of a connection (or some other sequence of asynchronous operations), a shared_ptr to the object would be bound into the handlers for all asynchronous operations associated with it. This works as follows:

  • When a single connection ends, all associated asynchronous operations complete. The corresponding handler objects are destroyed, and all shared_ptr references to the objects are destroyed.
  • To shut down the whole program, the io_service function stop() is called to terminate any run() calls as soon as possible. The io_service destructor defined above destroys all handlers, causing all shared_ptr references to all connection objects to be destroyed.

Typically your objects will chain asynchronous operations where the handlers are bound to member functions using boost::bind and boost::shared_from_this(). There are some examples that use this concept.

Stuff is missing from some of the comments above. Here's an example that helped me:

Boost enable_shared_from_this example

For me, I was struggling with errors about bad weak pointers. You HAVE to allocate your object in a shared_ptr fashion:

class SyncSocket: public boost::enable_shared_from_this<SyncSocket>

And allocate one like this:

boost::shared_ptr<SyncSocket> socket(new SyncSocket);

Then you can do things like:

socket->connect(...);

Lots of examples show you how to use shared_from_this() something like this:

boost::asio::async_read_until(socket, receiveBuffer, haveData,
        boost::bind(&SyncSocket::dataReceived, shared_from_this(), boost::asio::placeholders::error));

But was missing for me was using a shared_ptr to allocate the object to begin with.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!