C ++ | Comprensión y diferencia entre copia profunda y copia superficial

1. Constructor

En la programación orientada a objetos de C ++, el proceso del objeto se inicializa a través del constructor, que puede abrir espacio de memoria para el objeto en la memoria de la computadora y también puede proporcionar valores iniciales para los miembros de datos del objeto. El constructor es una función miembro especial con el mismo nombre que la clase y sin valor de retorno. Siempre que se crea un objeto (incluido el uso de new para crear dinámicamente un objeto), el sistema del compilador llamará automáticamente al constructor. Los constructores son como funciones generales y funciones miembro de clase distintas de las clases. Pueden estar sobrecargadas y tener parámetros predeterminados. La sobrecarga de constructores proporciona varios medios flexibles para la generación de objetos.

 Los constructores se dividen en constructor predeterminado (constructor predeterminado) y constructor definido por el usuario. Cuando el programador no define un constructor, el sistema proporcionará un constructor predeterminado sin parámetros, si el usuario define un constructor, el constructor predeterminado proporcionado por el compilador desaparece automáticamente.

 

2. Copiar constructor (copiar constructor)

La función del constructor de copia es un objeto existente para inicializar un objeto creado del mismo tipo, es un constructor especial con todas las características de un constructor general, y sus parámetros formales son referencias a esta clase de objetos. Los usuarios pueden definir constructores de copia específicos de acuerdo con sus problemas reales para realizar la transferencia de miembros de datos entre objetos similares. Si el usuario no declara el constructor de copia de la clase, el sistema generará automáticamente un constructor de copia predeterminado.La función de este constructor de copia predeterminado es copiar el valor inicial de cada miembro de datos al objeto recién creado. La declaración del constructor de copia es la siguiente:

        Nombre de clase (tipo y nombre de objeto);

gente de clase

{

público:

        vacío dipalay ()

        {

        }

privado:

        int a;

        nombre del personaje;

};

Hay tres situaciones en las que se llama al constructor de copias:

(1) Cuando se usa un objeto de la clase para inicializar otro objeto.

(2) Cuando el objeto se pasa como un parámetro de función, llame al constructor de copia

(3) Si el valor de retorno de la función es un objeto de la clase, se llama al constructor de copia cuando vuelve la llamada a la función.

 

3. Copia superficial y copia profunda

Copiar es copiar, crear una copia. Suponga que hay un objeto A y A tiene los atributos t1 y t2. Luego, al copiar A, obtengo B. B también debería tener los atributos t1 y t2, y cada atributo de los dos objetos A y B debería ser el mismo.

Para el atributo de tipo básico t1, no hay duda sobre la copia. Simplemente copie el valor para lograr el efecto de copia. Para el atributo t2 del tipo de referencia, copy tiene dos significados.

El primer nivel es que acabo de copiar la dirección a la que hace referencia t2 en t2 de B. Sí logró el mismo efecto de atributos. Se puede entender como una copia, pero de hecho, los atributos t2 en los dos objetos corresponden al mismo Un objeto. Operar en el objeto apuntado por t2 en el objeto B afectará el valor de t2 en el objeto A.

La segunda capa es que haré una copia completa del objeto apuntado por el t2 de A, supongamos que es o1, y supongamos que es o2, y le daré la nueva dirección de o2 al t2 de B. También se logra el efecto de copiar, y las operaciones sobre o2 señaladas por t2 de B no afectarán a o1 señaladas por t2 de A.

Los dos significados de copia corresponden a los conceptos de copia superficial y copia profunda: la primera capa es copia superficial y la segunda capa es copia profunda.

Con base en el contenido anterior, es fácil pensar que la copia superficial es más rápida que la copia profunda, sin embargo, en el sentido de la copia, en comparación con la copia profunda, falta la copia superficial.

 

En conclusión:

Copia superficial: copia de bits, constructor de copia, sobrecarga de asignación

Varios objetos comparten el mismo recurso, el mismo recurso se libera varias veces, se bloquea o se pierde memoria

Copia profunda: cada objeto comparte sus propios recursos y debe proporcionar explícitamente un constructor de copia y un operador de asignación.

En resumen: copia profunda y copia superficial se puede entender simplemente como: si una clase tiene recursos, cuando el objeto de esta clase pasa por un proceso de replicación, los recursos se redistribuyen, este proceso es copia profunda, de lo contrario, no hay reasignación de recursos. , que es una copia superficial.

 

Los ejemplos son los siguientes:

#include <iostream> usando el espacio de nombres std;

class CopyDemo {public: CopyDemo (int pa, char * cstr) // Constructor, dos parámetros {this-> a = pa; this-> str = new char [1024]; // Matriz de punteros, usar new dinámicamente Asignar espacio de almacenamiento en el montón strcpy (this-> str, cstr); // copiar sobre}

// No escrito, C ++ ayudará automáticamente a escribir un constructor de copia, la copia superficial solo copia el puntero, como en la sección de comentarios a continuación // CopyDemo (CopyDemo & obj) // {// this-> a = obj.a; // this-> str = obj.str; // Esta es una copia superficial causará problemas, copia profunda //}

  CopyDemo (CopyDemo & obj) // Los miembros de datos generales tienen punteros para escribir su propio constructor de copia, como sigue {this-> a = obj.a; // this-> str = obj.str; // Aquí está el problema de la copy, To deep copy this-> str = new char [1024]; // Debería escribir así if (str! = 0) strcpy (this-> str, obj.str); // Si tiene éxito, copie el contenido sobre }

  ~ CopyDemo () // Destructor {eliminar str;}

public: int a; // Defina un miembro de datos entero char * str; // Puntero de cadena};

int main () {CopyDemo A (100, "hola !!!");

  CopyDemo B = A; // Copia el constructor, copia A's 10 y hola !!! to B cout << "A:" << Aa << "," << A.str << endl; // salida A: 100, hola !!! cout << "B:" << Ba << "," << B.str << endl; // salida B: 100, hola !!!

  // Después de la modificación, se encuentra que se han cambiado tanto A como B. El motivo es una copia superficial. Los punteros de A y B apuntan al mismo lugar, y ambos cambian después de la modificación. Ba = 80; B.str [ 0] = 'k';

  cout << "A:" << Aa << "," << A.str << endl; // 输出 A: 100, ¡¡¡kello !!! cout << "B:" << Ba << "," << B.str << endl; // 输出 B: 80, ¡¡¡kello !!!

  return 0;}

Según el ejemplo anterior, la copia superficial solo copia el objeto en sí (incluidos los miembros de puntero), de modo que los punteros no nulos correspondientes en los miembros de diferentes objetos copiados apuntarán al mismo objeto, y el objeto al que hace referencia el puntero de miembro se convierte en compartido. No es posible eliminar de forma segura directamente a través de miembros de puntero (porque si elimina directamente, el puntero en el objeto no será válido, formando un llamado puntero salvaje, y es peligroso acceder a punteros no válidos; a menos que estos punteros tengan recuento de referencias u otros medios para garantizar la propiedad del objeto puntiagudo);

 La copia profunda se basa en la copia superficial, y el objeto al que apunta el puntero también se copia, lo que es relativamente caro, pero relativamente fácil de administrar.

resumen:

La diferencia más fundamental entre la copia profunda y la copia superficial es si realmente se debe obtener la entidad de copia de un objeto, no una referencia.

Suponga que B copia A, y cuando A se modifica, vea si B cambia:

Si B también cambia después, significa que es una copia superficial, ¡que es corta! (Modifique el mismo valor en la memoria del montón)

Si B no cambia, significa que es una copia profunda y autosuficiente. (Modificar diferentes valores en la memoria del montón)

Shallow Copy (shallowCopy) simplemente agrega un puntero a una dirección de memoria existente,

La copia profunda (deepCopy) agrega un puntero y solicita una nueva memoria, de modo que el puntero agregado apunte a esta nueva memoria.

En el caso de utilizar una copia profunda, la memoria no se liberará debido al error de liberar la misma memoria durante una copia superficial.

 

Si desea mejorar su capacidad de programación, ¡aprenda el lenguaje C y la programación C ++! Adelantar en una curva, ¡un paso más rápido!

[ Círculo de pingüinos de aprendizaje de lenguaje C C ++ ], compartir (código fuente, video de combate real del proyecto, notas del proyecto, tutorial introductorio básico)

¡Bienvenidos socios que cambian de carrera y aprenden programación, usan más información para aprender y crecer más rápido de lo que usted puede pensar!

Programación de libros de aprendizaje:

 

Programación de video de aprendizaje:

 

 

 

Supongo que te gusta

Origin blog.csdn.net/Hsuesh/article/details/112756397
Recomendado
Clasificación