Debo usar el rpp compartido o el único
He estado haciendo algunos objetos usando el modismo pimpl, pero no estoy seguro de si usarstd::shared_ptr
o std::unique_ptr
.
Entiendo que std::unique_ptr
es más eficiente, pero esto no es un problema para mí, ya que estos objetos son relativamente pesados de todos modos, por lo que el costo de std::shared_ptr
sobre std::unique_ptr
es relativamente menor.
Actualmente voy con std::shared_ptr
solo por la flexibilidad adicional. Por ejemplo, usar un std::shared_ptr
me permite almacenar estos objetos en un hashmap para acceso rápido sin dejar de ser capaz de devolver copias de estos objetos a las personas que llaman (ya que creo que cualquier iterador o referencia puede convertirse rápidamente en inválido).
Sin embargo, estos objetos de alguna manera realmente no se están copiando, ya que los cambios afectan a todas las copias, así que me preguntaba que tal vez usar std::shared_ptr
y permitir copias es algún tipo de anti-patrón o algo malo.
Es esto correcto?
4 answers
He estado haciendo algunos objetos usando el modismo pimpl, pero no estoy seguro de si usar
shared_ptr
ounique_ptr
.
Definitivamente unique_ptr
o scoped_ptr
.
Pimpl
no es un patrón, sino un modismo, que se ocupa de la dependencia en tiempo de compilación y la compatibilidad binaria. No debe afectar la semántica de los objetos, especialmente con respecto a su comportamiento de copia.
Puede usar cualquier tipo de puntero inteligente que desee debajo del capó, pero esos 2 garantizan que no compartirá accidentalmente la implementación entre dos objetos distintos, ya que requieren una decisión consciente sobre la implementación del constructor de copia y el operador de asignación.
Sin embargo, estos objetos de alguna manera realmente no se están copiando, ya que los cambios afectan a todas las copias, así que me preguntaba que tal vez usar
shared_ptr
y permitir copias es algún tipo de anti-patrón o algo malo.
No es un anti-patrón, de hecho, es un patrón: Aliasing. Ya utilizar, en C++, con los punteros y referencias. shared_ptr
ofrecen una medida adicional de "seguridad" para evitar referencias muertas, a costa de complejidad adicional y nuevos problemas (cuidado con los ciclos que crean fugas de memoria).
No relacionado con Pimpl
Entiendo que
unique_ptr
es más eficiente, pero esto no es un problema para mí, ya que estos objetos son relativamente pesados de todos modos, por lo que el costo deshared_ptr
sobreunique_ptr
es relativamente menor.
Si puede factorizar algún estado, es posible que desee echar un vistazo a la Peso mosca patrón.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-07 07:11:25
Si usas shared_ptr
, no es realmente el pimpl clásico
idioma (a menos que tome medidas adicionales). Pero la verdadera pregunta
es por eso que desea utilizar un puntero inteligente para empezar; es muy
claro donde el delete
debe ocurrir, y no hay problema de
seguridad de excepción u otro de que preocuparse. Como mucho,
un puntero inteligente le ahorrará una línea o dos de código. Y el
solo uno que tiene la semántica correcta es boost::scoped_ptr
,
y no creo que funcione en este caso. (IIRC, requiere
un tipo completo para ser instanciado, pero podría ser
Equivocada.)
Un aspecto importante del modismo pimpl es que su uso debe ser transparente para el cliente; la clase debe comportarse exactamente como si se implementó clásicamente. Esto significa o bien inhibir copia y asignación o implementación de copia profunda, a menos que la clase es inmutable (no hay funciones miembro no-const). Nada de lo habitual punteros inteligentes implementar copia profunda; se podría implementar uno, de por supuesto, pero probablemente todavía requeriría un tipo completo cada vez que se produce la copia, lo que significa que todavía tendría que proporcionar un constructor de copia definido por el usuario y un operador de asignación (ya que no pueden estar en línea). Dado esto, probablemente no vale la pena usar el puntero inteligente.
Una excepción es si los objetos son inmutables. En este caso, se
no importa si la copia es profunda o no, y shared_ptr
maneja la situación completamente.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-07 08:23:28
Cuando usa un shared_ptr
(por ejemplo, en un contenedor, luego busque esto y devuelva by-value), no está causando una copia del objeto al que apunta, simplemente una copia del puntero con un recuento de referencia.
Esto significa que si modifica el objeto subyacente desde varios puntos, entonces afecta los cambios en la misma instancia . Esto es exactamente para lo que está diseñado, por lo que no algunos anti-patrón!
Al pasar un shared_ptr
(como dicen los comentarios,) es es mejor pasar por referencia const y copiar (allí aumentando el recuento de referencias) cuando sea necesario. En cuanto a la devolución, caso por caso.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-13 07:01:36
Sí, por favor úselos. En pocas palabras, shared_ptr es una implementación de smart pointer. unique_ptr es una implementación de puntero automático:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-07 07:53:52