shared_ptr - передача по значению против передачи по ссылке - PullRequest
8 голосов
/ 16 марта 2011

Предположим, у меня есть:

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 ]

4 голосов
/ 16 марта 2011

EventDispatcher получает EventPtr и добавляет его в очередь, которая обрабатывается в другом потоке ... но какова подходящая сигнатура метода для метода отправки?

Любое предложениештраф;передача по константной ссылке, вероятно, будет более эффективной, поскольку не нужно будет изменять счетчик ссылок указателя.В любом случае push_back поместит копию указателя в очередь, поддерживая событие в активном состоянии, пока оно находится в очереди.

Опять же, что является подходящей сигнатурой метода для метода процесса?Мне интересно, могу ли я просто передать «голое» Событие * методу процесса?

Передача общего указателя (по значению или ссылке) четко документирует и обеспечит право собственности на событие иразрешить процессору удерживать его после вызова process(), если это необходимо.Передача необработанного указателя вносит неопределенность в собственность;процессору понадобится контракт, подтверждающий, что он не вступает во владение событием, и он не должен пытаться получить к нему доступ после окончания process().

1 голос
/ 16 марта 2011

В целом, не имеет большого значения, проходите ли вы по значению или по ссылке. В любом случае, счетчик ссылок будет увеличен, когда вы скопируете shared_ptr, чтобы поместить его в очередь.

Передача обнаженного указателя тоже подойдет, если вы будете осторожны, и у вас не останется два разных экземпляра shared_ptr с разным количеством ссылок: один в вызывающем и один в вызываемом.

Лично мне нравится опция передачи по значению, потому что это больше похоже на передачу реального указателя. Требование shared_ptr в качестве аргумента также напоминает программистам, вызывающим функцию, что она хочет, чтобы время жизни объекта превышало вызов функции, и что вызывающая сторона может в любом случае сохранить аргумент в shared_ptr в случае, если функция возвращается рано если выдается исключение и т. д.

0 голосов
/ 16 марта 2011

Обе функции отправки будут работать правильно.

В первом случае экземпляр общего указателя будет скопирован в стек, а затем снова скопирован при добавлении в очередь событий. Это означает копирование указателя и увеличение счетчика ссылок.

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

Во втором случае просто ссылка на существующий экземпляр будет передана функции и затем скопирована в очередь. Я бы использовал этот вариант.

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

При передаче общего указателя в process () вы также можете передать его по ссылке:

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