Diferencias entre unique_ptr y shared_ptr [duplicate]

7 minutos de lectura

Diferencias entre unique ptr y shared ptr duplicate
pequeñoB

Posibles duplicados:

grano: shared_ptr o unique_ptr
punteros inteligentes (boost) explicados

¿Alguien podría explicar las diferencias entre shared_ptr y unique_ptr?

  • Explicación del aumento de punteros inteligentes

    – legión

    29 de julio de 2011 a las 17:31


1646969893 604 Diferencias entre unique ptr y shared ptr duplicate
templatetypedef

Ambas clases son punteros inteligentes, lo que significa que automáticamente (en la mayoría de los casos) desasignarán el objeto al que apuntan cuando ya no se pueda hacer referencia a ese objeto. La diferencia entre los dos es cuántos punteros diferentes de cada tipo pueden hacer referencia a un recurso.

Cuando usas unique_ptrpuede haber como máximo uno unique_ptr apuntando a cualquier recurso. Cuando eso unique_ptr se destruye, el recurso se reclama automáticamente. porque solo puede haber uno unique_ptr a cualquier recurso, cualquier intento de hacer una copia de un unique_ptr provocará un error en tiempo de compilación. Por ejemplo, este código es ilegal:

unique_ptr<T> myPtr(new T);       // Okay
unique_ptr<T> myOtherPtr = myPtr; // Error: Can't copy unique_ptr

Sin embargo, unique_ptr puede ser movido usando la nueva semántica de movimiento:

unique_ptr<T> myPtr(new T);                  // Okay
unique_ptr<T> myOtherPtr = std::move(myPtr); // Okay, resource now stored in myOtherPtr

Del mismo modo, puedes hacer algo como esto:

unique_ptr<T> MyFunction() {
    unique_ptr<T> myPtr(/* ... */);

    /* ... */

    return myPtr;
}

Esta expresión significa “Le estoy devolviendo un recurso administrado. Si no captura explícitamente el valor devuelto, el recurso se limpiará. Si lo hace, ahora tiene la propiedad exclusiva de ese recurso”. De esta manera, se puede pensar en unique_ptr como un reemplazo más seguro y mejor para auto_ptr.

shared_ptr, por otro lado, permite que varios punteros apunten a un recurso determinado. cuando el último shared_ptr a un recurso se destruye, el recurso será desasignado. Por ejemplo, este código es perfectamente legal:

shared_ptr<T> myPtr(new T);       // Okay
shared_ptr<T> myOtherPtr = myPtr; // Sure!  Now have two pointers to the resource.

Internamente, shared_ptr usos conteo de referencia para rastrear cuántos punteros se refieren a un recurso, por lo que debe tener cuidado de no introducir ningún ciclo de referencia.

En breve:

  1. Utilizar unique_ptr cuando desea un único puntero a un objeto que se recuperará cuando se destruya ese único puntero.
  2. Utilizar shared_ptr cuando desea múltiples punteros al mismo recurso.

¡Espero que esto ayude!

  • unique_ptr puede ser un poco buggy con respecto a los eliminadores. shared_ptr siempre hará “lo correcto”, siempre y cuando haya sido creado con make_shared. Pero si creas un unique_ptr<Derived>luego conviértalo a unique_ptr<Base>, y si Derivado es virtual y Base no lo es, entonces el puntero se eliminará a través del tipo incorrecto y puede haber un comportamiento indefinido. Esto se puede arreglar con un tipo de borrador apropiado en el unique_ptr<T, DeleterType>pero el valor predeterminado es usar la versión más arriesgada porque es un poco más eficiente.

    – Aaron McDaid

    10/08/2015 a las 20:45

  • @AaronMcDaid Por defecto unique_ptr se comportará como un puntero en bruto que no puedes olvidar delete: si olvida hacer que el dtor sea virtual, está en usted.

    – chico curioso

    30/06/2018 a las 18:00

  • prefiero usar make_unique en lugar de new. Es más limpio, más seguro y más eficiente.

    – Submáquina

    27 de octubre de 2018 a las 14:18


  • @templatetypedef, ¿podría dar un ejemplo de cómo capturar el valor de retorno de su MyFunction() en otro puntero en el alcance de la persona que llama?

    – Vasilis

    11 de noviembre de 2018 a las 17:05

  • una gran respuesta

    – tae ha

    8 de marzo de 2021 a las 13:20

1646969894 894 Diferencias entre unique ptr y shared ptr duplicate
Kerrek SB

unique_ptr es el puntero inteligente liviano de elección si solo tiene un objeto dinámico en algún lugar para el cual una el consumidor tiene la responsabilidad exclusiva (por lo tanto, “única”), tal vez una clase contenedora que necesita mantener algún objeto asignado dinámicamente. unique_ptr tiene muy poca sobrecarga. No es copiable, sino movible. Su escribe es template <typename D, typename Deleter> class unique_ptr;entonces depende de dos parámetros de la plantilla.

unique_ptr es también lo que auto_ptr quería estar en el antiguo C++ pero no podía debido a las limitaciones de ese lenguaje.

shared_ptr por otro lado es un animal muy diferente. La diferencia obvia es que puede tener muchos consumidores compartiendo la responsabilidad de un objeto dinámico (por lo tanto, “compartido”), y el objeto solo se destruirá cuando todos los punteros compartidos hayan desaparecido. Además puedes tener observación punteros débiles que será informado inteligentemente si el puntero compartido que están siguiendo ha desaparecido.

Internamente, shared_ptr tiene mucho más en marcha: hay un recuento de referencias, que se actualiza atómicamente para permitir el uso en código concurrente. Además, hay muchas asignaciones en curso, una para un “bloque de control de referencia” de contabilidad interna y otra (a menudo) para el objeto miembro real.

Pero hay otra gran diferencia: el tipo de punteros compartidos es siempre template <typename T> class shared_ptr;y esto a pesar de que puede inicializarlo con eliminadores personalizados y con asignadores personalizados. El eliminador y el asignador se rastrean mediante el borrado de tipos y el envío de funciones virtuales, lo que aumenta el peso interno de la clase, pero tiene la enorme ventaja de que diferentes tipos de punteros compartidos de tipo T son todos compatibles, sin importar los detalles de eliminación y asignación. Así expresan verdaderamente el concepto de “responsabilidad compartida de T¡sin agobiar al consumidor con los detalles!

Ambas cosas shared_ptr y unique_ptr están diseñados para pasar por valor (con el requisito de movilidad obvio para el puntero único). Tampoco debería preocuparte por la sobrecarga, ya que su poder es realmente asombroso, pero si tienes una opción, prefiere unique_ptry solo uso shared_ptr si realmente necesitas responsabilidad compartida.

  • “diseñado para ser pasado por valor” ??

    – Ajay

    29 de noviembre de 2013 a las 5:56

  • Voté a favor porque estaba desconcertado acerca de dónde podría estar realmente el contador de referencia de shared_ptr (después de todo, múltiples shared_ptrs y un solo recurso compartido significan un solo contador de referencia compartido también, ¿verdad? Entonces, el contador no puede estar contenido dentro de shared_ptr). Esta es la primera explicación shared_ptr que he visto que responde a mi pregunta; Se asigna un contador de referencia separado. Presumiblemente, se asigna una vez en el conteo 0->1 y se libera una vez en el conteo 1->0, al igual que el recurso controlado.

    – Bill Foster

    7 de octubre de 2015 a las 2:53

  • ¿Cómo puedes pasarlo por valor si no puedes copiarlo?

    – astilla123

    03/06/2016 a las 22:00

  • @splinter123: ¡Moviéndolo!

    – KerrekSB

    3 de junio de 2016 a las 22:17

  • @Farzan: Sí, precisamente. O llama a la función con un temporal (al que no tiene acceso por definición), o necesita pasar algo como std::move(x) como argumento, lo que significa que x luego se mueve desde.

    – KerrekSB

    17 sep 2019 a las 22:59

único_ptr

es un puntero inteligente que posee un objeto exclusivamente.

ptr_compartido

es un puntero inteligente para la propiedad compartida. Son ambos copyable y movable. Varias instancias de puntero inteligente pueden poseer el mismo recurso. Tan pronto como el último puntero inteligente que posea el recurso quede fuera del alcance, el recurso se liberará.

1646969894 457 Diferencias entre unique ptr y shared ptr duplicate
neodelfos

Al envolver un puntero en un unique_ptr no puede tener varias copias de unique_ptr. los shared_ptr contiene un contador de referencia que cuenta el número de copias del puntero almacenado. Cada vez que un shared_ptr se copia, este contador se incrementa. Cada vez que un shared_ptr se destruye, este contador se decrementa. Cuando este contador llega a 0, el objeto almacenado se destruye.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad