Punteros inteligentes (C++ moderno)

En la programación de C++ moderna, incluye la biblioteca estándar de punteros inteligentes, que se utilizan para ayudar a garantizar que los programas que están libres de memoria y recursos fugas y son seguros de excepción.

Usos para los punteros inteligentes

Punteros inteligentes se definen en el std espacio de nombres en el <memory> archivo de encabezado.Son cruciales para el RAII o Initialialization es de adquisición de recurso lenguaje de programación.El objetivo principal de esta expresión es para asegurarse de que la adquisición de recursos se produce al mismo tiempo que se inicializa el objeto, para que todos los recursos para el objeto se crean y preparado para su uso en una línea de código.En términos prácticos, es el principio de RAII asignar a la propiedad de cualquier recurso asignado en el montón, por ejemplo, memoria asignada dinámicamente o identificadores de objeto del sistema — a un objeto asignado en la pila cuyo destructor contiene el código para eliminar o liberar el recurso y también cualquier código de limpieza asociado.

En la mayoría de los casos, cuando se inicializa un identificador de puntero o un recurso sin formato para que apunte a un recurso real, pasar el puntero a un puntero inteligente inmediatamente.En C++ moderno, sólo se utilizan punteros sin procesar en bloques de código pequeño de funciones limitadas de ámbito, bucles o auxiliar donde el rendimiento es fundamental y no hay ninguna posibilidad de confusión acerca de la propiedad.

En el ejemplo siguiente se comparan una declaración de puntero sin formato a una declaración de puntero inteligente.

void UseRawPointer()
{
    // Using a raw pointer -- not recommended.
    Song* pSong = new Song(L"Nothing on You", L"Bruno Mars"); 

    // Use pSong...

    // Don't forget to delete!
    delete pSong;   
}


void UseSmartPointer()
{
    // Declare a smart pointer on stack and pass it the raw pointer.
    unique_ptr<Song> song2(new Song(L"Nothing on You", L"Bruno Mars"));

    // Use song2...
    wstring s = song2->duration_;
    //...

} // song2 is deleted automatically here.

Como se muestra en el ejemplo, un puntero inteligente es una plantilla de clase que se declara en la pila y inicializar mediante el uso de un puntero sin formato que apunta a un objeto de montones.Después de inicializa el puntero inteligente, posee el puntero sin formato.Esto significa que el puntero inteligente es responsable de eliminar la memoria que especifica el puntero sin formato.El destructor de puntero inteligente contiene la llamada a eliminar y, debido a que el puntero inteligente se declara en la pila, su destructor se invoca cuando el puntero inteligente se sale del ámbito, incluso si se produce una excepción en algún lugar más arriba de la pila.

Tener acceso el puntero encapsulado mediante el uso de los operadores de puntero familiar, -> y *, que la clase de puntero inteligente sobrecarga para devolver el puntero sin formato encapsulado.

La expresión de puntero inteligente de C++ es similar a la creación de objetos en lenguajes como C#: crear el objeto y, a continuación, deje que el sistema tenga cuidado de eliminar en el momento correcto.La diferencia es que no independiente recolector de elementos no utilizados se ejecuta en segundo plano; memoria se administra mediante el estándar de C++ las reglas de ámbito para que el entorno de tiempo de ejecución es más rápido y eficaz.

Nota importanteImportante

Crear siempre punteros inteligentes en una línea independiente del código, nunca en una lista de parámetros, por lo que no se producirá una pérdida de recursos sutiles debido a ciertas reglas de asignación de la lista de parámetros.

El siguiente ejemplo muestra cómo un unique_ptr tipo de puntero inteligente desde la biblioteca de plantillas estándar podría utilizarse para encapsular un puntero a un objeto grande.


class LargeObject
{
public:
    void DoSomething(){}
};

void ProcessLargeObject(const LargeObject& lo){}
void SmartPointerDemo()
{    
    // Create the object and pass it to a smart pointer
    std::unique_ptr<LargeObject> pLarge(new LargeObject());

    //Call a method on the object
    pLarge->DoSomething();

    // Pass a reference to a method.
    ProcessLargeObject(*pLarge);

} //pLarge is deleted automatically when function block goes out of scope.

El ejemplo muestra los siguientes pasos esenciales para el uso de punteros inteligentes.

  1. El puntero inteligente se declara como una variable automática (local).(No utilice la new o malloc expresión en el puntero inteligente sí.)

  2. En el parámetro de tipo, especifique el tipo al que señala del puntero del encapsulado.

  3. Pasar un puntero sin formato a un new-objeto ed en el constructor de un puntero inteligente.(Algunas funciones de utilidad o constructores de puntero inteligente hace esto para usted.)

  4. Utilice la sobrecarga -> y * operadores para obtener acceso al objeto.

  5. Deje que el puntero inteligente eliminar el objeto.

Punteros inteligentes están diseñados para ser tan eficaz como sea posible tanto en términos de memoria y rendimiento.Por ejemplo, el miembro de datos sólo en unique_ptr es el puntero encapsulado.Esto significa que unique_ptr es exactamente el mismo tamaño que ese puntero, cuatro bytes o ocho bytes.Acceso a puntero encapsulado mediante el uso del puntero inteligente sobrecargado * y - > los operadores no es significativamente más lento que el acceso a los punteros sin procesar directamente.

Punteros inteligentes tienen sus propias funciones de miembro, que se puede obtener acceso mediante la notación "dot".Por ejemplo, algunos punteros inteligentes STL tienen una función de miembro de restablecimiento que libera la posesión del puntero.Esto es útil cuando desea liberar la memoria que son propiedad del puntero inteligente antes de que el puntero inteligente quede fuera de ámbito, como se muestra en el ejemplo siguiente.

void SmartPointerDemo2()
{
    // Create the object and pass it to a smart pointer
    std::unique_ptr<LargeObject> pLarge(new LargeObject());

    //Call a method on the object
    pLarge->DoSomething();

    // Free the memory before we exit function block.
    pLarge.reset();

    // Do some other work...

}

Punteros inteligentes suelen proporcionan una manera de tener acceso directamente a su puntero sin formato.Punteros inteligentes de STL tienen un get función de miembro para este fin, y CComPtr tiene un público p miembro de clase.Al proporcionar acceso directo al puntero subyacente, puede utilizar el puntero inteligente para administrar la memoria en su propio código y aun así pasar el puntero sin formato al código que no admite punteros inteligentes.

void SmartPointerDemo4()
{
    // Create the object and pass it to a smart pointer
    std::unique_ptr<LargeObject> pLarge(new LargeObject());

    //Call a method on the object
    pLarge->DoSomething();

    // Pass raw pointer to a legacy API
    LegacyLargeObjectFunction(pLarge.get());    
}

Tipos de punteros inteligentes

En la siguiente sección se resume los distintos tipos de punteros inteligentes que están disponibles en el entorno de programación de Windows y describe cuándo utilizarlas.

  • Punteros inteligentes de biblioteca estándar de C++
    Utilice estos punteros inteligentes como primera opción para encapsular los punteros a objetos de C++ antiguos sin formato (POCO).

    • unique_ptr
      Permite al propietario exactamente uno de puntero subyacente.Utilizar como opción predeterminada para POCO a menos que sepa con certeza que requieren un shared_ptr.Se pueden mover a otra persona, pero no copia o compartida.Reemplaza auto_ptr, que está en desuso.Comparar con boost::scoped_ptr.unique_ptres pequeño y eficiente; el tamaño es un puntero y admite las referencias de rvalue inserción rápida y la recuperación de las colecciones STL.Archivo de encabezado: <memory>.Para obtener más información, vea Cómo: Cree y use las instancias unique_ptr y unique_ptr Class.

    • shared_ptr
      Recuento de referencia puntero inteligente.Se utiliza cuando desea asignar un puntero sin formato a varios propietarios, por ejemplo, al devolver una copia de un puntero de un contenedor, pero desea conservar el original.El puntero sin formato no se elimina hasta que todos shared_ptr propietarios han salido del ámbito o de lo contrario han renunciado a propiedad.El tamaño es de dos punteros; uno para el objeto y otro para el bloque de control compartido que contiene el recuento de referencias.Archivo de encabezado: <memory>.Para obtener más información, vea Cómo: Cree y use las instancias shared_ptr y shared_ptr Class.

    • weak_ptr
      Caso especial puntero inteligente para su uso junto con shared_ptr.A weak_ptr proporciona acceso a un objeto que pertenece a uno o más shared_ptr las instancias, pero no participa en el recuento de referencias.Se utiliza cuando desea observar un objeto, pero no lo necesita para permanecer vivo.Necesario en algunos casos para romper las referencias circulares entre shared_ptr las instancias.Archivo de encabezado: <memory>.Para obtener más información, vea Cómo: Cree y use las instancias del weak_ptr y weak_ptr Class.

  • Punteros inteligentes para los objetos COM (programación de Windows clásico)
    Cuando se trabaja con objetos COM, ajustar los punteros de interfaz en un tipo de puntero inteligente apropiado.Active Template Library (ATL) define varios punteros inteligentes para diversos fines.También puede utilizar el _com_ptr_t tipo de puntero inteligente, que el compilador utiliza al crear clases contenedoras de .tlb (archivos).Es la mejor opción cuando no desea incluir los archivos de encabezado ATL.

  • Punteros inteligentes ATL para los objetos POCO
    Además de los punteros inteligentes para los objetos COM, ATL también define punteros inteligentes y las colecciones de punteros inteligentes, para los objetos de C++ antiguos sin formato.En la programación de Windows clásica, estos tipos son alternativas útiles a las colecciones STL, especialmente cuando no se requiere la portabilidad del código o cuando no desee combinar los modelos de programación de STL y ATL.

    • CAutoPtr (Clase)
      Puntero inteligente que aplica la propiedad única mediante la transferencia de propiedad en la copia.Comparable a la en desuso std::auto_ptr clase.

    • CHeapPtr (Clase)
      Puntero inteligente para los objetos que se asignan mediante el uso de la c malloc función.

    • CAutoVectorPtr (Clase)
      Puntero inteligente para arreglos de discos que se asignan mediante el uso de new[].

    • CAutoPtrArray (Clase)
      Clase que encapsula una matriz de CAutoPtr elementos.

    • CAutoPtrList (Clase)
      Clase que encapsula los métodos para manipular una lista de CAutoPtr los nodos.

Vea también

Otros recursos

Bienvenido a C++ (C++ moderno)

Referencia del lenguaje C++

Referencia de la biblioteca estándar de C++

información general: administración de memoria en C++