shared_ptr - pass by value vs pass by reference
Suppose I have:
typedef boost::shared_ptr<Event> EventPtr;
On one thread, I am creating an Event
and sending it off to get dispatched:
Event* event = new Event();
EventPtr eventPtr(event);
EventDispatcher::dispatch(eventPtr); //pseudocode
The EventDispatcher
receives an EventPtr and adds it to a queue that gets processed in another thread...but what is an appropriate method signature for the dispatch method?
dispatch(EventPtr event); //will push_back(event)
or
dispatch(const EventPtr& event); //will push_back(event);
Considering that my EventDispatcher has a queue:
typedef std::queue<EventPtr> EventQueue
EventQueue theQueue;
Then later, the other thread pops an Event off the queue and hands it off to something to process 开发者_如何学JAVAthe event:
EventPtr event = theQueue.front();
EventProcessor::process(event); //pseudocode
theQueue.pop();
Again, what is an appropriate method signature for the process
method? I'm wondering if I can just pass the naked Event*
to the process method?
I guess I'm wondering am I supposed to just pass by value so the reference count is accurate? I'm really only concerned about the fact that one thread is pushing onto the queue and another thread is popping off the queue and I'm not going to leak pointers somewhere...
Thanks!
The EventDispatcher receives an EventPtr and adds it to a queue that gets processed in another thread...but what is an appropriate method signature for the dispatch method?
Either suggestion is fine; passing by const reference will likely be more efficient, since it won't have to modify the pointer's reference count. In either case, push_back
will place a copy of the pointer on the queue, keeping the event alive while it's on the queue.
Again, what is an appropriate method signature for the process method? I'm wondering if I can just pass the naked Event* to the process method?
Passing the shared pointer (by value or reference) will clearly document and enforce the ownership of the event, and will allow the processor to keep hold of it after the call to process()
if it needs to. Passing a raw pointer introduces uncertainty into the ownership; the processor will need a contract stating that it isn't taking ownership of the event, and must not attempt to access it once process()
has ended.
In the big picture, it doesn't matter too much whether you pass by value or by reference. Either way, the reference count will be increased when you copy the shared_ptr
to push it onto the queue.
Passing the naked pointer is okay too as long as you're careful you don't end up with two different shared_ptr
instances with different reference counts, one in the caller and one in the callee.
Personally, I like the pass-by-value option because it feels more like passing a real pointer around. Requiring a shared_ptr
as an argument also reminds the programmers calling the function that it wants the lifetime of the object to exceed the function call and that the caller may want to store the argument in a shared_ptr
anyway in case the function returns early if an exception is thrown, etc.
Both dispatch functions will work properly.
In the first case, an instance of shared pointer will be copied on the stack and then copied again when adding to the event queue. This means copying of the pointer and increase of reference counter.
dispatch(EventPtr event); //will push_back(event)
In the second case just a reference to an existing instance will be passed to the function and then copied into the queue. I'd use this variant.
dispatch(const EventPtr& event); //will push_back(event);
When passing the shared pointer to process(), you can also pass it by reference:
class EventProcessor {
process(const EventPtr& event);
}
精彩评论