Pregunta

Todo,

Recientemente he publicado esta pregunta sobre DAL diseño. A partir de este parecería que pasa una referencia a un objeto en una función, con la función luego introducir ese objeto, sería una buena interfaz para una capa de C ++ de acceso a datos, por ejemplo.

  bool DAL::loadCar(int id, Car& car) {} 

Ahora estoy preguntando si se utiliza una referencia a un impulso :: shared_ptr sería mejor, por ejemplo.

  bool DAL::loadCar(int id, boost::shared_ptr<Car> &car)

¿Alguna idea? ¿Se ofrecen ventajas sobre el otro?

¿Cuáles serían las implicaciones de la aplicación de la corrección const a ambas llamadas?

Gracias de antemano.

¿Fue útil?

Solución

OSE dice: "Depende de lo que hace la función."

Sin embargo, creo que el aspecto más importante de lo anterior no es NULL si se permite o no, pero si la función almacena un puntero al objeto para su uso posterior. Si la función simplemente rellena algunos datos a continuación, me gustaría utilizar de referencia para las siguientes razones:

  • la función todavía puede ser utilizado por los clientes que no utilizan shared_ptr, que se utiliza para los objetos de la pila, etc.
  • Uso de la función con shared_ptr todavía es trivial - shared_ptr tiene operador de desreferencia que devuelve una referencia
  • NULL paso no es posible
  • teclear menos
  • No me gusta usar "cosas" cuando no tengo a

Si la función necesita para almacenar el puntero para su uso posterior o anticipar la función podría cambiar de tal manera que requerirá almacenar un puntero, a continuación, utilizar shared_ptr.

Otros consejos

Depende de lo que hace la función.

En general, una función que toma un puntero indica que las personas que llaman pueden llamar a esta función, incluso si no tienen un objeto para pasar a ella - que siempre pueden pasar NULL. Si que se ajuste a las especificaciones de la función, a continuación, utilizar un puntero (smart). referencia de pasada a contar punteros inteligentes por referencias en lugar de copiarlos es una optimización (y no una prematura, debo añadir), porque evita innecesariamente aumentar y disminuir el recuento de referencia, que puede, en entornos MT, ser un impacto de rendimiento notable.

Una función de tomar una referencia no const como un argumento espera ser pasado un objeto válido que podría cambiar. Las personas que llaman no pueden (legalmente) llamar a esa función a menos que tengan un objeto válido y no van a llamar a menos que estén dispuestos a tener la función de cambiar el estado del objeto. Si eso mejor se ajuste a las especificaciones de la función, utilice una referencia.

Si usted tiene que recibir un objeto válido (es decir, que no quiere la persona que llama para pasar NULL), entonces por todos los medios, no utilice impulso :: shared_ptr. Su segundo ejemplo pasa una referencia a un "puntero inteligente" .... ignorando los detalles, es un "puntero a puntero a Car". Debido a que es de referencia, el objeto shared_ptr no puede ser NULL .... pero no quiere decir que no puede tener un valor NULL (es decir, punto a un objeto "nulo").

No entiendo exactamente por qué se podría pensar que una referencia a un puntero inteligente sería "mejor" - no utilizar la función de llamada puntero inteligente ya

?

En cuanto a las implicaciones de la "const" ... ¿quiere decir algo así como

bool DAL::loadCar(int id, const Car& car) {}

? Si es así, sería contraproducente, se comunica al compilador el hecho de que "coche" no cambia (pero se supone que usted quiere que cambie!).

O ¿quiere decir hacer la función "const", algo así como

class DAL{
   bool loadCar(int id, Car& car) const;
}

En este último caso, comunicate al usuario compilador / API que el método "loadCar" no modifica el objeto DAL. Es una buena idea hacerlo si esto es cierto - que no sólo permite a algunas optimizaciones del compilador, pero en general es una buena cosa para especificar en el "contrato" (función de firma) que la función no hace ninguna modificación a DAL, especialmente si hacer esta suposición implícita en su código (de esta manera se asegura de que este se mantiene fiel, y que en el futuro nadie va a modificar la función "loadCar" de una manera que va a cambiar el objeto "DAL")

En el primer caso, simplemente pasa un coche y "rellenar" con la información. Por ejemplo, puede crear un coche "default" y luego llenarlo. Veo un inconveniente en esto: en que no es muy OO tener dos clases de coches: Un pobre, por defecto, inútil, coche "vacío", y uno realmente lleno en el coche después de que proviene de la función. Para mí, un coche es un coche, por lo que debe ser un coche válido (uno puedo conducir desde la ubicación de A a B, por ejemplo, uno que pueda acelerar, frenar, arrancar, parar). Antes y después de la función

Me suelen trabajar con punteros tradicionales, no Boost (sin ningún problema, por cierto), así que realmente no puedo comentar sobre esta última alternativa.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top