Pregunta

¿Qué es un puntero inteligente y cuando debo usar uno?

¿Fue útil?

Solución

ACTUALIZACIÓN

Esta respuesta es bastante viejo, y así describe lo que es "bueno" en el tiempo, que fue de punteros inteligentes proporcionada por el Impulso de la biblioteca.Debido a que C++11, la biblioteca estándar se ha proporcionado suficiente inteligente punteros de tipos, y por lo que debe favorecer el uso de std::unique_ptr, std::shared_ptr y std::weak_ptr.

También hay std::auto_ptr.Es muy parecida a la de un ámbito de puntero, excepto que también tiene el "especiales" peligrosas de la capacidad para ser copiado, que inesperadamente se transfiere la propiedad! Es obsoleto en los nuevos estándares, por lo que no debería usar.El uso de la std::unique_ptr en su lugar.

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.

RESPUESTA ANTERIOR

Un puntero inteligente es una clase que envuelve un 'raw' (o 'desnudo') C++ puntero, para gestionar el tiempo de vida del objeto señalado.No existe un único puntero inteligente tipo, pero todas tratan de abstraer un raw puntero en una forma práctica.

Punteros inteligentes debe ser preferido sobre primas de punteros.Si usted siente que necesita para el uso de punteros (considerar en primer lugar si realmente hacer), que normalmente se desea utilizar un puntero inteligente, ya que esto puede aliviar muchos de los problemas con raw, punteros, principalmente olvidar para eliminar el objeto y la fuga de memoria.

Con raw de los punteros, 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

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

void f()
{
    {
       std::unique_ptr<MyObject> ptr(new MyObject());
       ptr->DoSomethingUseful();
    } // 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 std::unique_ptr casos no puede ser copiado.Esto evita 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.

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

Una más compleja puntero inteligente de la política consiste en el recuento de referencias, el puntero.Esto permite que el puntero para ser copiado.Cuando el último de la "referencia" para el objeto se destruye, se elimina el objeto.Esta política se implementa por boost::shared_ptr y std::shared_ptr.

void f()
{
    typedef std::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 útil 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 a la 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 {
   std::shared_ptr<Owner> other;
};

std::shared_ptr<Owner> p1 (new Owner());
std::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 Impulso y C++11 han definido una weak_ptr para definir una débil (incontables) referencia a una shared_ptr.

Otros consejos

Aquí hay una respuesta simple para estos días de C++moderno:

  • ¿Qué es un puntero inteligente?
    Es un tipo cuyos valores pueden ser utilizados como punteros, pero que proporciona la característica adicional de la gestión automática de memoria:Cuando un puntero inteligente ya no está en uso, la memoria señala que se cancela la asignación (ver también la definición más detallada en Wikipedia).
  • Cuando debo usar uno?
    En el código que implica el seguimiento de la propiedad de una porción de la memoria, la asignación o de la asignación;el puntero inteligente evita la necesidad de hacer estas cosas de forma explícita.
  • Pero que inteligente puntero se debe utilizar en cual de esos casos?
    • Uso std::unique_ptr cuando usted no tiene previsto hacer varias referencias al mismo objeto.Por ejemplo, su uso es un puntero a la memoria que obtiene asigna ingresar en algún ámbito y de-asignados en salir del ámbito de aplicación.
    • Uso std::shared_ptr cuando queremos hacer referencia a su objeto desde varios lugares y no quiere que su objeto a ser de-asignado hasta que todas estas referencias son ellos mismos han ido.
    • Uso std::weak_ptr cuando queremos hacer referencia a su objeto desde varios lugares para esas referencias para el que es aceptar a ignorar y deallocate (para que sólo tenga en cuenta que el objeto se ha ido cuando intenta eliminar).
    • No utilice el boost:: punteros inteligentes o std::auto_ptr excepto en casos especiales que usted puede leer sobre si debe.
  • Hey, no me pregunte cual usar!
    Ah, pero lo que realmente quería, lo admito.
  • Así que cuando debo uso regular de los punteros, entonces?
    Principalmente en el código que es ajeno a la memoria la propiedad.Esto suele ser en las funciones que obtener un puntero de algún otro lugar y no destinan ni de la asignación, y no guarde una copia del puntero que outlasts su ejecución.

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

Pequeña intro está disponible en la página Punteros Inteligentes - ¿Qué, Por Qué, Que?.

Uno de los smart simple-tipo de puntero es std::auto_ptr (capítulo 20.4.5 de estándar de C++), lo que permite a desasignar la memoria de forma automática cuando está fuera de alcance y que es más robusto que el simple puntero de uso cuando se producen excepciones, aunque menos flexible.

Otro tipo es conveniente boost::shared_ptr que implementa el recuento de referencias y automáticamente se cancela la asignación de memoria cuando no hay referencias a objeto permanece.Esto ayuda a evitar pérdidas de memoria y 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, capítulo Capítulo 20.Punteros Inteligentes.Algunos de los temas cubiertos:

Definiciones proporcionadas por Chris, Sergdev y Llyod son correctos.Yo prefiero una definición más simple, aunque, para mantener mi nivel de vida simple:Un puntero inteligente es simplemente una clase que sobrecarga la -> y * a los operadores.Lo que significa que su objeto semánticamente parece un puntero, pero se puede hacer de manera enfriador de 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.

Un puntero inteligente es como un regular (escrito) puntero, como "char*", excepto cuando el puntero sale del ámbito, a continuación, lo que apunta a que también se elimina.Usted puede usarlo como si fuera un puntero normal, mediante el uso de "->", pero no si usted necesita un verdadero puntero a los datos.Por eso, puede utilizar "&*ptr".

Es útil para:

  • Los objetos que deben ser asignados con los nuevos, pero que le gustaría tener la misma vida útil que algo en esa pila.Si el objeto es asignado a un puntero inteligente, entonces se eliminan cuando el programa sale que la función/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 es virtual, que es casi siempre una buena cosa que hacer).

Usted puede no desea utilizar un puntero inteligente cuando:

  • ...el puntero no debería en realidad el dueño de los datos...es decir, cuando se le acaba la utilización de los datos, pero quieres que 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 sentarse 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 podrían apuntar a los mismos datos.(Hay, sin embargo, aún más inteligente punteros que se encargará de que...que se llama el recuento de referencias.)

Vea también:

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

El más comúnmente utilizado punteros inteligentes son std::tr1::shared_ptr (o boost::shared_ptr), y, menos comúnmente, 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 escenarios, incluyendo los casos en que los objetos necesitan "pasar a través de DLL límites" (la pesadilla caso si es diferente libcs se utilizan entre el código y los archivos Dll).

Un puntero inteligente es un objeto que actúa como un puntero, pero, además, proporciona control sobre la construcción, destrucción, copiar, mover y eliminar.

Uno puede implementar su propio puntero inteligente, pero muchas bibliotecas también proporcionan puntero inteligente implementaciones cada uno con diferentes ventajas y desventajas.

Por ejemplo, Boost proporciona el siguiente puntero inteligente implementaciones:

  • shared_ptr<T> es un puntero a T el uso de un número de referencia para determinar cuando el objeto ya no es necesario.
  • scoped_ptr<T> es un puntero eliminan automáticamente cuando se sale del ámbito.No cesión No es posible.
  • intrusive_ptr<T> es otro de conteo de referencia de puntero.Proporciona un mejor rendimiento que los shared_ptr, pero requiere el tipo T para proporcionar su propio mecanismo contador de referencias.
  • weak_ptr<T> es un débil puntero, trabajando en conjunto con shared_ptr para evitar las referencias circulares.
  • shared_array<T> es como shared_ptr, pero para las matrices de T.
  • scoped_array<T> es como scoped_ptr, pero para las matrices de T.

Estos son sólo uno lineal descripciones de cada uno y puede ser utilizado como por necesidad, para más detalles y ejemplos, uno puede mirar en la documentación de Boost.

Además, el estándar de C++ biblioteca ofrece tres punteros inteligentes; std::unique_ptr de propiedad exclusiva, std::shared_ptr el uso compartido de la propiedad y std::weak_ptr. std::auto_ptr existía en C++03, pero ahora es obsoleto.

Aquí está el Enlace para respuestas similares : http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

Un puntero inteligente es un objeto que actúa, se ve y se siente como un puntero normal, pero ofrece más funcionalidad.En C++, punteros inteligentes se implementan como plantilla de clases que encapsulan un puntero y reemplazar el estándar de los operadores de puntero.Se tiene un número de ventajas sobre ordinario de los punteros.Que están garantizados para ser inicializado como null punteros o apuntadores a un montón de objetos.Direccionamiento indirecto a través de un puntero nulo es marcada.No eliminar nunca es necesario.Los objetos se libera automáticamente cuando el último puntero a ellos se ha ido.Un problema importante con estos punteros inteligentes es que a diferencia de los punteros, no respetan la herencia.Punteros inteligentes son poco atractivos para polimórficos código.A continuación se realiza un ejemplo de la implementación de punteros inteligentes.

Ejemplo:

template <class X>
class smart_pointer
{
          public:
               smart_pointer();                          // makes a null pointer
               smart_pointer(const X& x)            // makes pointer to copy of x

               X& operator *( );
               const X& operator*( ) const;
               X* operator->() const;

               smart_pointer(const smart_pointer <X> &);
               const smart_pointer <X> & operator =(const smart_pointer<X>&);
               ~smart_pointer();
          private:
               //...
};

Esta clase de implementar un smart puntero a un objeto de tipo X.El objeto en sí se encuentra en el montón.Aquí es cómo se usa:

smart_pointer <employee> p= employee("Harris",1333);

Como otros operadores sobrecargados, p se comportará como un puntero normal,

cout<<*p;
p->raise_salary(0.5);

http://en.wikipedia.org/wiki/Smart_pointer

En ciencias de la computación, un puntero inteligente es un tipo de datos abstracto que simula un puntero mientras que la prestación de características adicionales, tales como automático la recolección de basura o la comprobación de límites.Estas características adicionales son la intención de para reducir los errores causados por el uso indebido de los punteros, mientras que la retención de la eficiencia.Punteros inteligentes suelen seguir la pista de los objetos que se elija para la el propósito de la gestión de la memoria.El el mal uso de punteros es una fuente importante de errores:la constante de asignación, desasignación y hacer referencia a que se debe ser realizada por un programa escrito el uso de punteros hace muy probable que algunas pérdidas de memoria se va a producir.Punteros inteligentes tratar de evitar que la memoria fugas, haciendo que el recurso de cancelación automática:cuando el puntero a un objeto (o el último de una serie de punteros) se destruye, por ejemplo, porque se sale del ámbito, el objeto de punta es destruido también.

Sea T una clase en este tutorial Los punteros en C++ se pueden dividir en 3 tipos :

1) Raw punteros :

T a;  
T * _ptr = &a; 

Tienen una dirección de memoria a una ubicación en la memoria.Utilizar con precaución , ya que los programas se vuelven complejas de difícil seguir la pista.

Punteros con const de datos o la dirección { Leer al revés }

T a ; 
const T * ptr1 = &a ; 
T const * ptr1 = &a ;

Puntero a un tipo de datos T, que es una constante.Lo que significa que usted no puede cambiar el tipo de datos mediante el puntero.es decir *ptr1 = 19 ;no va a funcionar.Pero usted puede mover el puntero.es decir ptr1++ , ptr1-- ;etc de trabajo.Leer al revés :puntero a tipo T que se const

  T * const ptr2 ;

Una constante de puntero a un tipo de datos T .Lo que significa que usted no puede mover el puntero, pero usted puede cambiar el valor apuntado por el puntero.es decir *ptr2 = 19 funciona, pero ptr2++ ; ptr2-- etc no va a funcionar.Leer al revés :const puntero a un tipo de T

const T * const ptr3 ; 

Una constante de puntero a una constante de tipo de datos T .Sentido de que no puede mover el puntero ni puede cambiar el tipo de datos puntero a ser el puntero.es decir . ptr3-- ; ptr3++ ; *ptr3 = 19; no va a funcionar

3) Punteros Inteligentes : { #include <memory> }

Comparte Puntero:

  T a ; 
     //shared_ptr<T> shptr(new T) ; not recommended but works 
     shared_ptr<T> shptr = make_shared<T>(); // faster + exception safe

     std::cout << shptr.use_count() ; // 1 //  gives the number of " 
things " pointing to it. 
     T * temp = shptr.get(); // gives a pointer to object

     // shared_pointer used like a regular pointer to call member functions
      shptr->memFn();
     (*shptr).memFn(); 

    //
     shptr.reset() ; // frees the object pointed to be the ptr 
     shptr = nullptr ; // frees the object 
     shptr = make_shared<T>() ; // frees the original object and points to new object

Implementa mediante el conteo de referencias para mantener un seguimiento de cuántas "cosas" seleccione el objeto apuntado por el puntero.Cuando este contador llega a 0 , el objeto se elimina automáticamente , es decir, se opuso se elimina cuando todos los share_ptr señalando el objeto queda fuera del ámbito de aplicación.Esto elimina el dolor de cabeza de tener que eliminar los objetos que tiene asignado el uso de nuevo.

Débil Puntero : Ayuda a lidiar con referencia cíclica, la cual surge cuando el uso Compartido Puntero Si usted tiene dos objetos apuntados por dos punteros y hay una interna compartida puntero que apunta a cada uno de los otros comparten puntero a continuación se hará una referencia cíclica y el objeto no se eliminan cuando se comparte punteros salen de su ámbito.Para resolver este problema , cambie el miembro interno de un shared_ptr a weak_ptr.Nota :Para tener acceso al elemento señalado por una débil puntero del uso de bloqueo() , devuelve un weak_ptr.

T a ; 
shared_ptr<T> shr = make_shared<T>() ; 
weak_ptr<T> wk = shr ; // initialize a weak_ptr from a shared_ptr 
wk.lock()->memFn() ; // use lock to get a shared_ptr 
//   ^^^ Can lead to exception if the shared ptr has gone out of scope
if(!wk.expired()) wk.lock()->memFn() ;
// Check if shared ptr has gone out of scope before access

Ver : Cuando se std::weak_ptr útil?

Único Puntero : Peso ligero puntero inteligente con la propiedad exclusiva.Utilizar cuando el puntero apunta a los objetos únicos, sin compartir los objetos entre los punteros.

unique_ptr<T> uptr(new T);
uptr->memFn(); 

//T * ptr = uptr.release(); // uptr becomes null and object is pointed to by ptr
uptr.reset() ; // deletes the object pointed to by uptr 

Para cambiar el objeto señalado por el único ptr , uso mover la semántica

unique_ptr<T> uptr1(new T);
unique_ptr<T> uptr2(new T);
uptr2 = std::move(uptr1); 
// object pointed by uptr2 is deleted and 
// object pointed by uptr1 is pointed to by uptr2
// uptr1 becomes null 

Referencias :Esencialmente pueden ser entendidas como const punteros, es decir, un puntero que es constante y no se puede mover con una mejor sintaxis.

Ver : ¿Cuáles son las diferencias entre una variable puntero y de referencia variable en C++?

r-value reference : reference to a temporary object   
l-value reference : reference to an object whose address can be obtained
const reference : reference to a data type which is const and cannot be modified 

Referencia :https://www.youtube.com/channel/UCEOGtxYTB6vo6MQ-WQ9W_nQ Gracias Andre por señalar esta cuestión.

Un puntero inteligente es una clase, un contenedor normal de un puntero.A diferencia de la normal punteros, smart punto del círculo de la vida se basa en un recuento de referencia (la cantidad de tiempo que el puntero inteligente objeto es asignado).Así que cada vez que un puntero inteligente es asignada a otro, el recuento de referencia interno plus plus.Y siempre que el objeto queda fuera del ámbito de aplicación, el número de referencia de menos de menos.

Automático puntero, aunque similar, es totalmente diferente de puntero inteligente.Es una buena clase que cancela la asignación de los recursos cuando un sistema automático de puntero de objeto queda fuera del ámbito de la variable.En cierta medida, se hace un puntero (a la memoria asignada dinámicamente) funciona de forma similar a una pila variable (asignado estáticamente en la compilación de tiempo).

Punteros inteligentes son aquellos en los que usted no tiene que preocuparse acerca de la Memoria De la Asignación de Recursos, el Intercambio y la Transferencia.

Usted puede utilizar muy bien estos puntero en la manera similar a como la asignación de obras en Java.En java Recolector de elementos no utilizados el truco, mientras que en Punteros Inteligentes, el truco está hecho por los Destructores.

Las respuestas existentes son buenos, pero no cubren qué hacer cuando un puntero inteligente no es el (completa) respuesta al problema que se intenta resolver.

Entre otras cosas (bien explicado en otras respuestas) utilizando un puntero inteligente es una posible solución ¿Cómo podemos utilizar una clase abstracta como una función de tipo de retorno? que ha sido marcado como un duplicado de esta pregunta.Sin embargo, la primera pregunta para preguntar si la tentación para especificar un resumen (o en realidad, cualquier) de la clase base como un tipo de retorno en C++ es "¿qué significa realmente?".Hay una buena discusión (con más referencias) idiomáticas de programación orientada a objetos en C++ (y cómo esto es diferente a otros idiomas) en la documentación de la impulsar el puntero del contenedor de la biblioteca.En resumen, en C++ tienes que pensar acerca de la propiedad.Que de punteros inteligentes ayudar, pero no son la única solución, o siempre una solución completa (no te dan polimórficos copia) y no siempre son una solución que desea exponer en su interfaz (y una función de devolución de los sonidos de un montón de cosas como una interfaz).Podría ser suficiente para devolver una referencia, por ejemplo.Pero en todos estos casos (smart puntero, puntero del contenedor o simplemente devuelve una referencia) ha cambiado el regreso de un valor a alguna forma de referencia.Si usted realmente necesita copiar usted puede necesitar agregar más repetitivo "modismo" o se mueven más allá de la idiomáticas (o no) la programación orientada a objetos en C++ para más genérico polimorfismo de uso de las bibliotecas como Adobe Poli o Boost.TypeErasure.

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