773 votos

¿Qué es un puntero inteligente y cuándo se debe utilizar?

¿Qué es un puntero inteligente y cuándo se debe utilizar?

993voto

Lloyd Puntos 7111

Un puntero inteligente es una clase que envuelve un "desnudo" C++ puntero, para gestionar el tiempo de vida del objeto señalado.

Con "desnudo" punteros de C++, el programador tiene que explícitamente destruir el objeto cuando ya no es útil.

// Need to create the object to achieve some goal
MyObject* ptr = new MyObject(); 
ptr->DoSomething();// Use the object in some way.
delete ptr; // Destroy the object. Done with it.
// Wait, what if DoSomething() raises an exception....

Un puntero inteligente por comparación define una política como para cuando se destruye el objeto. Usted todavía tiene que crear el objeto, pero usted ya no tiene que preocuparse acerca de la destrucción de la misma.

SomeSmartPtr<MyObject> ptr(new MyObject());
ptr->DoSomething(); // Use the object in some way.

// Destruction of the object happens, depending 
// on the policy the smart pointer class uses.

// Destruction would happen even if DoSomething() 
// raises an exception

La más simple política de uso implica el alcance de puntero inteligente objeto contenedor, tales como el implementado por boost::scoped_ptr o std::unique_ptr.

void f()
{
    {
       boost::scoped_ptr<MyObject> ptr(new MyObject());
       ptr->DoSomethingUseful();
    } // boost::scopted_ptr goes out of scope -- 
      // the MyObject is automatically destroyed.

    // ptr->Oops(); // Compile error: "ptr" not defined
                    // since it is no longer in scope.
}

Tenga en cuenta que scoped_ptr instancias no pueden ser copiados. Esto impide que el puntero de ser eliminado varias veces (de manera incorrecta). Sin embargo, puede pasar referencias a ella en torno a otras funciones de la llamada.

El ámbito de los punteros son útiles cuando se quieren atar el tiempo de vida del objeto a un determinado bloque de código, o si es incorporado como miembro de datos dentro de otro objeto, el tiempo de vida del objeto. El objeto existe, hasta el que contiene el bloque de código que se exitted, o hasta que el objeto que contiene en sí es destruido.

Más complejo puntero inteligente de la política consiste en el recuento de referencias de el puntero. Esto permite que el puntero para ser copiado. Cuando el último de la "referencia" el objeto es destruido, se elimina el objeto. Esta política es implementada por boost::shared_ptr y std::shared_ptr.

void f()
{
    typedef std::tr1::shared_ptr<MyObject> MyObjectPtr; // Nice short alias.
    MyObjectPtr p1; // Empty
    {
        MyObjectPtr p2(new MyObject());
        // There is now one "reference" to the created object
        p1=p2; // Copy the pointer.
        // There are now two references to the object.
    } // p2 is destroyed, leaving one reference to the object.
} // p1 is destroyed, leaving a reference count of zero. 
  // The object is deleted.

Referencia contado punteros son muy útiles cuando la vida de su objeto es mucho más complicado, y no está ligada directamente a una sección de código o a otro objeto.

Hay un inconveniente para referencia contado punteros - la posibilidad de crear un colgando de referencia.

// Create the smart pointer on the heap
MyObjectPtr* pp = new MyObjectPtr(new MyObject())
// Hmm, we forgot to destroy the smart pointer,
// because of that, the object is never destroyed!

Otra posibilidad es la creación de referencias circulares.

struct Owner {
   boost::shared_ptr<Owner> other;
};

boost::shared_ptr<Owner> p1 (new Owner());
boost::shared_ptr<Owner> p2 (new Owner());
p1->other = p2; // p1 references p2
p2->other = p1; // p2 references p1

// Oops, the reference count of of p1 and p2 never goes to zero!
// The objects are never destroyed!

Para evitar este problema, tanto de refuerzo y C++11 definir weak_ptr definir una débil (incontables) referencia a un shared_ptr.

Tenga en cuenta también que la biblioteca estándar de C++ que hace es definir un tipo especial de puntero inteligente std::auto_ptr. Es muy parecida a la de un ámbito puntero, excepto que también tiene el "especial" peligroso capacidad para ser copiado, que inesperadamente se transfiere la propiedad!

std::auto_ptr<MyObject> p1 (new MyObject());
std::auto_ptr<MyObject> p2 = p1; // Copy and transfer ownership. 
                                 // p1 gets set to empty!
p2->DoSomething(); // Works.
p1->DoSomething(); // Oh oh. Hopefully raises some NULL pointer exception.

67voto

sergtk Puntos 3109

Puntero inteligente es un puntero-como el tipo con alguna funcionalidad adicional, por ejemplo. memoria automática de desasignación, el recuento de referencias, etc.

Pequeña introducción está disponible en la página de Punteros Inteligentes - ¿qué, por Qué, Que?.

Uno de los smart simple-tipo de puntero es std::auto_ptr (capítulo 20.4.5 de C++ estándar), lo que permite cancelaciones de asignación de memoria automáticamente cuando está fuera de alcance y es más robusto que el simple puntero de uso cuando las excepciones son de tiro, aunque menos flexible.

Otro tipo es conveniente boost::shared_ptr que implementa el recuento de referencias y automáticamente desasignar memoria cuando no hay referencias a objeto de permanecer, esto ayuda a evitar fugas de memoria, es fácil de usar para implementar RAII.

Tema se trata en profundidad en el libro "las Plantillas de C++: La Guía Completa" por David Vandevoorde, Nicolai M. Josuttis, el capítulo Capítulo 20. Punteros Inteligentes. Algunos de los temas cubiertos:

23voto

Sridhar Iyer Puntos 1186

Las definiciones de Chris,Sergdev y Llyod es correcto. Yo prefiero una definición más simple, aunque, para mantener mi nivel de vida simple: Puntero inteligente es simplemente una clase que sobrecarga -> y * los operadores. Lo que significa que su objeto semánticamente se ve como un puntero, pero se puede hacer de manera más fresco cosas, incluyendo el recuento de referencias, la destrucción automática, etc. shared_ptr y auto_ptr son suficientes en la mayoría de los casos, pero vienen con su propio conjunto de pequeñas idiosincrasias..

15voto

markets Puntos 3598

Un puntero inteligente es como un regular (escrito) puntero, como "char*", excepto cuando el puntero del mismo se va fuera de alcance, a continuación, lo que apunta a que también se elimina. Se puede utilizar como lo haría con un puntero normal, mediante el uso de "->", pero no si usted necesita un verdadero puntero a los datos. Por eso, puede usar "&*ptr".

Es útil para:

  • Los objetos que deben ser asignados con los nuevos, pero que le gustaría tener la misma vida como algo en esa pila. Si el objeto asignado a un puntero inteligente, entonces se eliminan cuando el programa sale que la función o bloque.

  • Datos de miembros de las clases, de modo que cuando el objeto es eliminado todos los datos que son propiedad se elimina así, sin ningún código especial en el destructor (usted tendrá que asegurarse de que el destructor virtual, que es casi siempre una buena cosa para hacer).

Puede que no desee utilizar un puntero inteligente cuando:

  • ... el puntero no debería en realidad el dueño de los datos... es decir, cuando usted está usando sólo los datos, sino que quieren que para sobrevivir a la función donde se hace referencia a él.
  • ... el puntero inteligente no es en sí va a ser destruido en algún momento. Usted no quiere que permanezca en la memoria que nunca se destruye (como en un objeto que se asigna de forma dinámica, pero no será eliminado explícitamente).
  • ... dos punteros inteligentes pueden apuntar a los mismos datos. (Hay, sin embargo, incluso el más inteligente de los punteros que se encargará de... que se llama el recuento de referencias.)

Ver también:

11voto

Chris Jester-Young Puntos 102876

La mayoría de los tipos de punteros inteligentes de manejar desechar el puntero a objeto para usted. Es muy práctico porque no tienes que pensar sobre la eliminación de objetos manualmente.

El más comúnmente utilizado de punteros inteligentes son std::tr1::shared_ptr (o boost::shared_ptr), y, con menor frecuencia, std::auto_ptr. Recomiendo el uso regular de shared_ptr.

shared_ptr es muy versátil y se ocupa de una gran variedad de eliminación de los escenarios, incluidos los casos en que los objetos necesitan ser "aprobado en los límites DLL" (la pesadilla de caso de diferentes libcs se utilizan entre el código y los archivos Dll).

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X