could someone summarize in a few succinct words how the boost shared_from_this<>()
smart pointer should be used, particularly from the perspective of registering handlers in the io_service using the bind function.
EDIT: Some of the responses have asked for more context. Basically, I'm looking for "gotchas", counter-intuitive behaviour people have observed using this mechanism.
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.
来源:https://stackoverflow.com/questions/3629557/boost-shared-from-this