Ok, así que la última vez que escribí en C++ para vivir, std::auto_ptr fue todo el sexual, lib tenía disponible, y boost::shared_ptr era toda la rabia. Nunca he mirado en el otro puntero inteligente tipos impulso proporcionado. Entiendo que C++11 ahora ofrece algunos de los tipos de impulso vino, pero no todos ellos.

Así que, ¿alguien tiene un algoritmo simple para determinar cuándo utilizar puntero inteligente? Preferiblemente incluyendo asesoramiento sobre mudo punteros (raw punteros como T*) y el resto de la potenciación de punteros inteligentes. (Algo así como este sería genial).

Véase también std::auto_ptr a std::unique_ptr
Estoy realmente esperando que alguien viene con una buena mano de diagrama de flujo como este STL diagrama de flujo de selección.
Oh, eso es de hecho una buena! Yo FAQized.
posibles duplicados de ¿Qué es un puntero inteligente y cuando debo usar?
Eso no es ni siquiera cerca de ser un duplicado. Los enlaces pregunta dice: «Cuando debo usar el un puntero inteligente», y esta pregunta es «¿Cuándo debo usar el esta punteros inteligentes?», es decir, esta es la categorización de los diferentes usos de la norma de punteros inteligentes. Los enlaces pregunta no hacerlo. La diferencia es aparentemente pequeño, pero es un grande.

OriginalEl autor sbi | 2012-01-02

4 Comentarios

  1. 173

    De propiedad compartida:

    El shared_ptr y weak_ptr el estándar adoptado son prácticamente los mismos que los de su Impulsar contrapartes. El uso de ellas cuando las necesite para compartir un recurso y no sé cuál va a ser el último ser vivo. Uso weak_ptr para observar el recurso compartido sin influir en su vida, no para romper los ciclos. Ciclos con shared_ptr no sucede habitualmente – dos recursos no puede ser dueño de uno a otro.

    Nota que Boost ofrece, además,shared_array, lo que podría ser una alternativa adecuada para shared_ptr<std::vector<T> const>.

    Siguiente, Boost ofrece intrusive_ptr, que son una solución ligera de si el recurso de referencia de ofertas contado a la gestión de ya y que desea adoptar a la RAII principio. Esto no fue adoptado por la norma.

    Única propiedad:

    Impulsar también tiene un scoped_ptr, que no es copiable y para la cual no se puede especificar un deleter. std::unique_ptr es boost::scoped_ptr en los esteroides y debe ser su opción predeterminada cuando se necesita un puntero inteligente. Le permite especificar un deleter en sus argumentos de plantilla y es muebles, a diferencia de boost::scoped_ptr. También es totalmente utilizable en contenedores STL, siempre y cuando no uses las operaciones que necesitan copiable tipos (obviamente).

    Nota de nuevo, que el Impulso tiene una matriz versión: scoped_array, que la norma unificada exigiendo std::unique_ptr<T[]> parcial de especialización que se delete[] el puntero en lugar de deleteing (con la default_deleter). std::unique_ptr<T[]> también ofrece operator[] en lugar de operator* y operator->.

    Nota que std::auto_ptr todavía está en la norma, pero es obsoleto.
    §D.10 [depr.auto.ptr]

    La plantilla de clase auto_ptr está en desuso. [ Nota: La plantilla de clase unique_ptr (20.7.1) proporciona una solución mejor. —nota final de la ]

    La propiedad:

    Uso tonto punteros (raw punteros) o referencias para no poseer referencias a los recursos y cuando se sabe que el de los recursos de sobrevivir a el objeto de referencia /alcance. Prefieren las referencias y su uso en crudo, punteros cuando se necesita la aceptación de valores null o la capacidad de reset.

    Si quieres un no-ser dueño de referencia a un recurso, pero no sabe si el recurso de sobrevivir el objeto que hace referencia a ella, pack de los recursos en una shared_ptr y el uso de un weak_ptr – usted puede probar si el padre shared_ptr está vivo con lock, que devolverá un shared_ptr que no es null si el recurso existe todavía. Si desea probar si el recurso está muerto, uso expired. El dos de mayo de sonido similar, pero son muy diferentes en la cara de la ejecución simultánea, como expired sólo garantiza su valor de retorno para que la sola declaración. Un aparentemente inocente de la prueba como

    if(!wptr.expired())
      something_assuming_the_resource_is_still_alive();

    es una potencial condición de carrera.

    En el caso de la propiedad, usted debe probablemente prefieren las referencias a los punteros a menos que usted no necesita ninguna propiedad de y la capacidad de reset cuando las referencias no se corte, incluso entonces es posible que desee considerar la posibilidad de reescribir el objeto original a ser un shared_ptr y el no poseer puntero a ser un weak_ptr
    No me refiero a referencia a puntero, pero en lugar de referencia en lugar de puntero. Si no hay propiedad, a menos que usted necesita la capacidad de reset (o la aceptación de valores null, pero la nulabilidad sin ser capaz de restablecer sería bastante limitado), se puede utilizar un plano de referencia en lugar de un puntero en el primer lugar.
    Ah, ya veo. 🙂 Sí, las referencias no son malas por que, yo personalmente los prefiero en estos casos. Voy a añadir.
    shared_array<T> es una alternativa a shared_ptr<T[]> no shared_ptr<vector<T>>: no puede crecer.
    Eso es… exactamente lo que yo escribí? Me dijo que es un ejemplo de una posible condición de carrera.

    OriginalEl autor Xeo

  2. 125

    Decidir qué puntero inteligente de utilizar es una cuestión de propiedad. Cuando se trata de la gestión de recursos, objeto de Un posee objeto B si está en control de la vida útil del objeto B. Por ejemplo, los miembros de variables son propiedad de sus respectivos objetos, porque la vida de los miembros de variables está ligada a la vida del objeto. Elige punteros inteligentes basadas en la forma en que el objeto es de su propiedad.

    Nota de que la propiedad en un sistema de software es independiente de la propiedad como podríamos pensar fuera de software. Por ejemplo, una persona podría «propio» de su casa, pero eso no significa necesariamente que un Person objeto tiene control sobre la vida de un House objeto. Confundir estos mundo real los conceptos con el software de conceptos es una manera del seguro-fuego para que se programa a sí mismo en un agujero.


    Si usted tiene el único de la propiedad del objeto, utilice std::unique_ptr<T>.

    Si usted ha compartido la propiedad del objeto…

    – Si no hay ciclos en la propiedad, el uso std::shared_ptr<T>.

    – Si hay ciclos, definir una «dirección» y el uso std::shared_ptr<T> en una dirección y std::weak_ptr<T> en el otro.

    Si el objeto posee, pero hay posibilidades de no tener dueño, uso normal punteros T* (por ejemplo, consejos para los padres).

    Si el objeto posee (o no ha garantizado la existencia), el uso de referencias T&.


    Advertencia: Ser consciente de los costos de punteros inteligentes. En la memoria o rendimiento de los entornos limitados, podría ser beneficioso para sólo uso normal de los punteros con un manual de plan para la gestión de la memoria.

    De los costes:

    • Si tienes un custom deleter (por ejemplo, utilizar la asignación de las piscinas), a continuación, se incurrirá en gastos generales por puntero que puede evitarse fácilmente mediante la eliminación manual.
    • std::shared_ptr tiene la sobrecarga de un recuento de referencia incremento en la copia, además de una disminución en la destrucción seguido de un 0-recuento de verificación con la eliminación del objeto. Dependiendo de la aplicación, esto puede inflar su código y causar problemas de rendimiento.
    • Tiempo de compilación. Como con todas las plantillas, punteros inteligentes contribuyen negativamente a los tiempos de compilación.

    Ejemplos:

    struct BinaryTree
    {
        Tree* m_parent;
        std::unique_ptr<BinaryTree> m_children[2]; //or use std::array...
    };

    Un árbol binario no es dueño de su padre, pero la existencia de un árbol que implica la existencia de su padre o madre (o nullptr para root), por lo que utiliza un puntero normal. Un árbol binario (con valor semántica) tiene la propiedad única de sus hijos, así que esos son std::unique_ptr.

    struct ListNode
    {
        std::shared_ptr<ListNode> m_next;
        std::weak_ptr<ListNode> m_prev;
    };

    Aquí, la lista de nodos que posee su siguiente y anterior listas, por lo que podemos definir una dirección y utilizar shared_ptr para la próxima y weak_ptr de prev para romper el ciclo.

    Para el ejemplo del árbol binario algunas personas sugieren el uso de shared_ptr<BinaryTree> para los niños y weak_ptr<BinaryTree> para la relación padre.
    Depende de si el Árbol tiene un valor semántica o no. Si la gente va a ser la referencia de su árbol en el exterior, incluso una vez que el árbol de código fuente es destruido, entonces sí, compartido/débil puntero combo sería lo mejor.
    Si un objeto posee y está garantizado que existe, entonces ¿por qué no una referencia.
    Si utiliza la referencia, usted no puede cambiar nunca el padre, que puede o no puede obstaculizar el diseño. Para el equilibrio de los árboles, que impediría.
    +1, pero usted debe agregar una definición de «propiedad» en la primera línea. A menudo me encuentro a mí mismo tener que indicar claramente que se trata de la vida & la muerte del objeto, no la propiedad de un dominio más específico de significado.

    OriginalEl autor Peter Alexander

  3. 19

    Uso unique_ptr<T> todo el tiempo, excepto cuando usted necesita el recuento de referencias, en cuyo caso el uso de shared_ptr<T> (y para casos muy raros, weak_ptr<T> para evitar ciclos de referencia). En casi todos los casos, transferible única propiedad está bien.

    Raw punteros: Bueno, sólo si necesita covariante devuelve, no poseer señalando que puede suceder. No están tremendamente útil en caso contrario.

    Matriz de punteros: unique_ptr tiene una especialización para T[] que llama automáticamente a delete[] en el resultado, así que usted puede hacerlo de forma segura unique_ptr<int[]> p(new int[42]); por ejemplo. shared_ptr usted todavía necesita una costumbre deleter, pero no especializado compartido o conjunto único puntero. Por supuesto, este tipo de cosas son lo mejor suele ser reemplazado por std::vector de todos modos. Por desgracia shared_ptr no proporciona una matriz de acceso a la función, por lo que todavía habría que llamar manualmente get(), pero unique_ptr<T[]> proporciona operator[] en lugar de operator* y operator->. En cualquier caso, usted tiene a la comprobación de límites a sí mismo. Esto hace que shared_ptr un poco menos amigable para el usuario, aunque podría decirse que los genéricos de la ventaja y sin aumento de la dependencia hace unique_ptr y shared_ptr los ganadores.

    Ámbito de punteros: se Hizo irrelevante por unique_ptr, como auto_ptr.

    No hay realmente nada más que eso. En C++03, sin mover la semántica de esta situación era muy complicada, pero en C++11, el consejo es muy simple.

    Hay todavía utiliza para otros punteros inteligentes, como intrusive_ptr o interprocess_ptr. Sin embargo, son muy nicho y completamente innecesario en el caso general.

    También, cruda punteros para la iteración. Y para el parámetro de salida de búferes, donde el búfer es propiedad de la persona que llama.
    Ya he editado para incluir tales.
    Hmm, la forma en que lo leí, son situaciones que son covariante de retorno y no poseer. Una reescritura puede ser bueno si usted quiere la unión, en lugar de intersección. También me gustaría decir que la iteración es digno de mención especial también.
    std::unique_ptr<T[]> proporciona operator[] en lugar de operator* y operator->. Es cierto que todavía hay que hacer obligada comprobación de ti mismo aunque.

    OriginalEl autor Puppy

  4. 4

    Casos de cuándo utilizar unique_ptr:

    • Métodos de fábrica
    • Miembros que son punteros (pimpl incluido)
    • Almacenar punteros en stl containters (para evitar que se mueve)
    • Uso de local de grandes objetos dinámicos

    Casos de cuándo utilizar shared_ptr:

    • Intercambio de objetos a través de los subprocesos
    • De intercambio de objetos en general

    Casos de cuándo utilizar weak_ptr:

    • Mapa grande que actúa como una referencia general (ex. un mapa de todos los sockets abiertos)

    Siéntase libre de editar y añadir más

    OriginalEl autor Lalaland

Dejar respuesta

Please enter your comment!
Please enter your name here