2011-03-16 16 views
8

Supongamos que tengo:shared_ptr - paso por valor vs pase por referencia

typedef boost::shared_ptr<Event> EventPtr; 

Por un hilo, estoy creando una Event y enviarlo a conseguir enviado:

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

El EventDispatcher recibe un EventPtr y lo agrega a una cola que se procesa en otro hilo ... pero ¿cuál es una firma de método apropiada para el método de envío?

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

o

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

Teniendo en cuenta que mi EventDispatcher tiene una cola:

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

Luego, más tarde, el otro hilo aparece un evento de la cola y se lo entrega fuera a algo para procesar el evento:

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

De nuevo, ¿cuál es una firma de método apropiada para el método process? Me pregunto si puedo pasar el Event* desnudo al método de proceso.

Supongo que me pregunto ¿se supone que debo pasar el valor por lo que el recuento de referencias es preciso? Solo estoy preocupado por el hecho de que un hilo se está metiendo en la cola y otro hilo está saliendo de la cola y no voy a filtrar punteros en algún lugar ...

¡Gracias!

Respuesta

4

EventDispatcher recibe un EventPtr y lo agrega a una cola que se procesa en otro hilo ... pero ¿cuál es la firma de método apropiada para el método de envío?

Cualquiera de las dos sugerencias está bien; pasar por referencia constante probablemente sea más eficiente, ya que no tendrá que modificar el recuento de referencia del puntero. En cualquier caso, push_back colocará una copia del puntero en la cola, manteniendo vivo el evento mientras está en la cola.

Nuevamente, ¿cuál es la firma de un método apropiado para el método de proceso? Me pregunto si puedo pasar el evento * desnudo al método de proceso.

Al pasar el puntero compartida (por valor o referencia) documentará claramente y hacer respetar la propiedad del evento, y permitirá que el procesador para mantener el asimiento de él después de la llamada a process() si es necesario. Pasar un puntero sin formato introduce incertidumbre en la propiedad; el procesador necesitará un contrato que indique que no se apropia del evento, y no debe intentar acceder una vez que el process() haya finalizado.

1

A grandes rasgos, no importa demasiado si pasa por valor o por referencia. De cualquier manera, el recuento de referencias aumentará cuando copie el shared_ptr para insertarlo en la cola.

Pasar el puntero desnudo también está bien siempre que tenga cuidado de no terminar con dos instancias diferentes shared_ptr con recuentos de referencias diferentes, uno en la persona que llama y otro en la llamada.

Personalmente, me gusta la opción de pasar por valor porque se siente más como pasar un puntero real. Exigir un shared_ptr como argumento también recuerda a los programadores que llaman a la función que quiere que el tiempo de vida del objeto exceda la llamada de función y que la persona que llama puede guardar el argumento en un shared_ptr de todos modos en caso de que la función retorne lanzado, etc.

0

Ambas funciones de envío funcionarán correctamente.

En el primer caso, una instancia de puntero compartido se copiará en la pila y luego se copiará nuevamente cuando se agregue a la cola de eventos. Esto significa copiar el puntero y aumentar el contador de referencia.

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

En el segundo caso sólo una referencia a una instancia existente se pasa a la función y luego se copia en la cola. Yo usaría esta variante.

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

Al pasar el puntero compartida con el proceso(), también puede pasar por referencia:

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