shared_ptr - 按值传递vs按引用传递

时间:2011-03-16 19:36:56

标签: c++ boost smart-pointers

假设我有:

typedef boost::shared_ptr<Event> EventPtr;

在一个帖子上,我正在创建一个Event并将其发送给派遣人员:

Event* event = new Event();
EventPtr eventPtr(event);
EventDispatcher::dispatch(eventPtr);  //pseudocode

EventDispatcher收到一个EventPtr并将其添加到另一个线程中处理的队列中...但是这个调度方法的适当方法签名是什么?

dispatch(EventPtr event);  //will push_back(event)

dispatch(const EventPtr& event);  //will push_back(event);

考虑到我的EventDispatcher有一个队列:

typedef std::queue<EventPtr> EventQueue
EventQueue theQueue;

然后,另一个线程将一个事件从队列中弹出并将其移交给处理该事件的东西:

EventPtr event = theQueue.front();
EventProcessor::process(event);  //pseudocode
theQueue.pop();

同样,process方法的适当方法签名是什么?我想知道我是否可以将裸Event*传递给流程方法?

我想我想知道我应该只是按值传递所以引用计数是准确的吗?我真的只关心一个线程正在推送到队列而另一个线程从队列中弹出的事实,我不会在某个地方泄漏指针......

谢谢!

3 个答案:

答案 0 :(得分:4)

  

EventDispatcher接收一个EventPtr并将其添加到另一个线程中处理的队列中......但是这个调度方法的适当方法签名是什么?

任何一个建议都没问题;通过const引用传递可能会更有效,因为它不必修改指针的引用计数。在任何一种情况下,push_back都会将指针的副本放在队列中,使事件在队列中保持活动状态。

  

同样,过程方法的适当方法签名是什么?我想知道我是否可以将裸体事件*传递给过程方法?

传递共享指针(通过值或引用)将清楚地记录并强制执行事件的所有权,并且如果需要,将允许处理器在调用process()之后保持它。传递原始指针会给所有权带来不确定性;处理程序需要一份合同,声明它没有获得该事件的所有权,并且在process()结束后不得尝试访问它。

答案 1 :(得分:1)

从大图来看,无论是通过价值还是通过参考,都无关紧要。无论哪种方式,当您复制shared_ptr以将其推送到队列时,引用计数将会增加。

传递裸指针也没关系,只要你小心你没有最终得到两个不同引用计数的shared_ptr实例,一个在调用者中,一个在被调用者中。

就个人而言,我喜欢pass-by-value选项,因为它更像是传递一个真正的指针。要求shared_ptr作为参数也会提醒程序员调用函数,它希望对象的生命周期超过函数调用,并且调用者可能希望将参数存储在shared_ptr中以防万一如果抛出异常等,函数会提前返回

答案 2 :(得分:0)

两个调度功能都能正常工作。

在第一种情况下,共享指针的实例将被复制到堆栈上,然后在添加到事件队列时再次复制。这意味着复制指针并增加引用计数器。

dispatch(EventPtr event);  //will push_back(event)

在第二种情况下,只将对现有实例的引用传递给该函数,然后将其复制到队列中。我会使用这种变体。

dispatch(const EventPtr& event);  //will push_back(event);

将共享指针传递给process()时,您也可以通过引用传递它:

class EventProcessor {
    process(const EventPtr& event);
}