[Notas de C ++] Punteros inteligentes de C ++

Lee este artículo

1. Ideas de diseño de puntero inteligente

2. El puntero inteligente es fácil de usar

3. ¿Por qué no se recomienda utilizar auto_ptr

4. Cómo elegir qué puntero inteligente usar

Ideas de diseño de puntero inteligente

En el artículo anterior sobre pits comunes al usar punteros C / C ++, resumí varios pits que pueden encontrarse al usar punteros en C / C ++. El más común son las pérdidas de memoria. Recuerde el siguiente ejemplo.
[Notas de C ++] Punteros inteligentes de C ++
[Notas de C ++] Punteros inteligentes de C ++

En este ejemplo, debido a que se lanza una excepción, la declaración de eliminación no tiene posibilidad de ejecutarse, lo que provoca una pérdida de memoria. Por supuesto, para estas decenas de líneas de programa, puede agregar un delete t a la declaración catch para evitarlo.

Pero, ¿y si se trata de un proyecto de ingeniería con decenas de líneas W? ¡Creo que te desmoronarás! Entonces, ¿hay una mejor manera? La respuesta es sí.

Sabemos que para las variables locales ordinarias (variables locales no estáticas), cuando salen de su alcance, el sistema operativo las liberará automáticamente; y también sabemos que el objeto de clase se llama automáticamente cuando se libera la clase. Incinerador de basuras.

Entonces pensamos: si Test * t no es una variable de puntero ordinaria, sino un objeto de clase, y el paso de liberar memoria dinámica se implementa en el destructor de la clase; entonces, siempre que la variable de puntero salga del alcance Se llamará al destructor para lograr el propósito de liberar memoria dinámica. Esta es la idea de los punteros inteligentes.

De acuerdo con el supuesto anterior, no es difícil implementar un puntero inteligente simple, de la siguiente manera:

class SmartPointer 
{
    private:
        Test* ptr;
    public:
        SmartPointer(Test* p) 
        {
         ptr = p;
        }
         ~SmartPointer() //析构函数释放资源
         {
         delete p;
         }
};

Entonces, cómo usarlo, solo necesita cambiar un poco sobre la base del código original, de la siguiente manera:

[Notas de C ++] Punteros inteligentes de C ++

El puntero inteligente de C ++ es fácil de usar

Por supuesto, el puntero inteligente que implementamos por nosotros mismos es solo para ilustrar la idea del diseño del puntero inteligente, que es muy burda. En uso normal, no es necesario que usted mismo defina punteros inteligentes. C ++ ya nos ha proporcionado punteros inteligentes listos para usar.

C ++ STL nos proporciona cuatro tipos de punteros inteligentes: auto_ptr, unique_ptr, shared_ptr y debil_ptr; entre ellos, auto_ptr es proporcionado por C ++ 98, y se recomienda abandonarlo en C ++ 11. En cuanto a la razón, hablaré de ello más adelante; y unique_ptr, shared_ptr Y débil_ptr se agregó a STL con la llegada de C ++ 11.

El uso de punteros inteligentes en realidad no es difícil, como se muestra a continuación:
[Notas de C ++] Punteros inteligentes de C ++
[Notas de C ++] Punteros inteligentes de C ++

¿Por qué no se recomienda utilizar auto_ptr

Primero observe la siguiente declaración:

auto_ptr<int> px(new int(8));
auto_ptr<int> py;
py = px;

¿Qué logrará la declaración de asignación anterior? Si px y py son punteros ordinarios, los dos punteros apuntarán al mismo objeto int asignado dinámicamente. Esto es inaceptable, porque el programa puede intentar borrar el mismo objeto dos veces, una cuando expira px y otra cuando expira py. Sabemos que la misma memoria no se puede borrar dos veces. Para evitar este problema, existen principalmente los dos métodos siguientes:

  • Establecer el concepto de propiedad (propiedad). Para un objeto específico, solo se puede poseer un puntero inteligente al mismo tiempo. Por ejemplo, cuando el puntero inteligente A apunta al objeto x, cuando se ejecuta B = A, el puntero A original pierde la propiedad de x, por lo que solo el objeto es propiedad El constructor del puntero inteligente eliminará el objeto, unique_ptr y auto_ptr están usando esta estrategia.

  • Cree punteros más inteligentes y realice un seguimiento de la cantidad de punteros inteligentes que hacen referencia a objetos específicos. Esto se llama recuento de referencias. Por ejemplo, al asignar un valor, el recuento aumentará en 1 y cuando el puntero expire, el recuento disminuirá en 1. Cuando se reduce a 0, se llama a eliminar. Esta es la estrategia adoptada por shared_ptr.

Por supuesto, se debe utilizar la misma estrategia para los constructores de copias.

Echemos un vistazo a por qué se recomienda abandonar auto_ptr en C ++ 11. Observe el siguiente ejemplo:
[Notas de C ++] Punteros inteligentes de C ++
[Notas de C ++] Punteros inteligentes de C ++
De los resultados de ejecución del programa, cuando se ejecuta la instrucción de asignación py = px, el programa se bloquea cuando visita px. La razón es que la instrucción de asignación py = px transfiere la propiedad del objeto de px a py, y px se ha convertido en un puntero nulo, por supuesto, será un error acceder a px nuevamente.

Entonces, ¿qué sucede si usa unique_ptr o shared_ptr? Probémoslo. Primero veamos la situación de unique_ptr:
[Notas de C ++] Punteros inteligentes de C ++
[Notas de C ++] Punteros inteligentes de C ++
vea si usa unique_ptr, obtendrá un error al compilar en este caso. Es decir, aunque unique_ptr también usa el modelo de propiedad como auto_ptr, el programa no esperará cuando use unique_ptr. Se bloquea durante el tiempo de ejecución, exponiendo posibles errores durante la compilación

Ok, echemos un vistazo a la situación shared_ptr:
[Notas de C ++] Punteros inteligentes de C ++
[Notas de C ++] Punteros inteligentes de C ++
se ejecuta normalmente cuando se usa shared_ptr, porque shared_ptr usa el recuento de referencias. Después de que se ejecuta la instrucción de asignación py = px, px y py apuntan a la misma memoria, pero cuando liberas el espacio, necesitas juzgar de antemano Por tanto, el tamaño del valor de recuento de referencia no provoca el error de eliminar un objeto varias veces.

Cómo elegir qué puntero inteligente

Después de comprender estos tipos de punteros inteligentes, naturalmente puede pensar en una pregunta: ¿Qué puntero inteligente debería usarse en aplicaciones de proyectos reales? Según las características de estos punteros inteligentes, se dan las siguientes sugerencias:

  • Si desea usar múltiples punteros al mismo objeto en el programa, debe usar shared_ptr; por ejemplo, hay un contenedor STL que contiene punteros, y ahora se usa un algoritmo STL que admite operaciones de copia y asignación para manipular los elementos punteros del contenedor, entonces Deberías usar shared_ptr. No puede usar unique_ptr (error del compilador) y auto_ptr (comportamiento incierto).

  • Si el programa no necesita usar varios punteros al mismo objeto, puede usar unique_ptr; si la función usa new para asignar memoria y devuelve un puntero a la memoria, es una buena opción declarar su tipo de retorno como unique_ptr. De esta forma, la propiedad se transfiere al unique_ptr que acepta el valor de retorno, y el puntero inteligente será el responsable de llamar a delete.

  • Cuando se cumplen las condiciones requeridas por unique_ptr, también se puede usar auto_ptr, pero unique_ptr es una mejor opción.

para resumir

Este artículo solo resume el uso básico de los punteros inteligentes en general, y hay muchos puntos que vale la pena señalar en el uso real. Los artículos posteriores continuarán resumiendo estos detalles. En resumen, el proceso de aprender C ++ es un proceso de pisar el pozo.

Lectura recomendada:

[Bienestar] Uso compartido de videos de cursos de calidad en línea recopilados por mí mismo (
Parte 1 ) [Bosque de protocolos] Cartero y oficina de correos (Descripción general del protocolo de red)
[Estructura de datos y algoritmo] Explicación fácil de entender del orden de bits
[Notas de C ++] Programación concurrente de C ++ 11 (1) ) Inicie el viaje del hilo
[Notas de C ++] Errores comunes en el uso de punteros de C / C ++
[Notas de C ++] Explicación detallada de bibliotecas estáticas y dinámicas (en)

Codificación

¡El productor de códigos tiene la manera correcta de proporcionarle artículos técnicos fáciles de entender para facilitar la tecnología!
[Notas de C ++] Punteros inteligentes de C ++

Céntrese en compartir resumen de conocimientos de pila de tecnología de fondo del servidor

Bienvenido a prestar atención a la comunicación y al progreso común.

Supongo que te gusta

Origin blog.51cto.com/15006953/2552128
Recomendado
Clasificación