2010-04-17 23 views
45

Duplicar posible:
What is the difference between a deep copy and a shallow copy?copia profunda vs copia superficial

¿Cuál es la diferencia entre copia profunda y superficial. ¿Qué tipo de copia hace un constructor de copia?

+2

Duplicado de http://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy –

+0

La primera pregunta es un dup, pero puedo No encuentro el segundo, aunque podría ser porque no está claramente indicado. @Ankur: en su segunda pregunta, ¿está preguntando sobre el constructor de copia predeterminado? – outis

+1

Los términos "deep versus shallow copy" no se suelen usar en C++, ya que no se asignan especialmente al lenguaje. En Java y en varios otros idiomas, la distinción es más útil debido a su semántica basada en referencias, lo que hace que la copia superficial sea inevitable en la mayoría de los casos. En C++, donde los objetos se copian por valor, las copias superficiales verdaderas son muy raras, pero el constructor de copia predeterminado tampoco implementará una copia profunda. Los términos simplemente no tienen sentido en C++ – jalf

Respuesta

10

El ejemplo por excelencia de esto es una serie de punteros a estructuras u objetos (que son mutables).

A copia poco profunda copia la matriz y mantiene referencias a los objetos originales.

A copia profunda copiará (clonará) los objetos para que no guarden relación con el original. Implícito en esto es que el objeto mismo está profundamente copiado. Aquí es donde se pone difícil porque no hay forma real de saber si algo fue copiado profundamente o no.

El constructor de copia se utiliza para iniciar el nuevo objeto con el objeto previamente creado de la misma clase. Por defecto, el compilador escribió una copia superficial. La copia superficial funciona bien cuando la asignación de memoria dinámica no está involucrada porque cuando se trata de asignación de memoria dinámica, ambos apuntan hacia la misma ubicación de memoria en un montón. Por lo tanto, para eliminar este problema escribimos copia profunda para que ambos objetos tengan su propia copia de atributos en un recuerdo

Para leer los detalles con ejemplos completos y explicaciones, puede ver el artículo Constructors and destructors.

El constructor de copia predeterminado es poco profundo. Puede hacer que sus propios constructores de copia sean profundos o superficiales, según corresponda. Ver C++ Notes: OOP: Copy Constructors.

+3

Debe ser * una matriz de ** punteros a ** objetos mutables * –

+0

Un buen ejemplo es Boost :: GIL donde las vistas son copias superficiales de objetos de imagen (contenedores de píxeles). Las copias locales/temporales de píxeles se realizan cuando se accede a ellas a través del objeto de vista. – jiggunjer

46

copia superficial:

Algunos miembros de la copia puede hacer referencia a los mismos objetos que el original:

class X 
{ 
private: 
    int i; 
    int *pi; 
public: 
    X() 
     : pi(new int) 
    { } 
    X(const X& copy) // <-- copy ctor 
     : i(copy.i), pi(copy.pi) 
    { } 
}; 

Aquí, el pi miembro del original y de copiado X objeto se producirá tanto seleccione el mismo int.


copia profunda:

Todos los miembros de la original, se clonan (de forma recursiva, si es necesario). No hay objetos compartidos:

class X 
{ 
private: 
    int i; 
    int *pi; 
public: 
    X() 
     : pi(new int) 
    { } 
    X(const X& copy) // <-- copy ctor 
     : i(copy.i), pi(new int(*copy.pi)) // <-- note this line in particular! 
    { } 
}; 

Aquí, el miembro de la piX objeto original y el copiado se apuntan a diferentes objetos int, pero ambos tienen el mismo valor.


El constructor de copia por defecto (que se proporciona de forma automática si no se proporciona uno mismo) crea copias solamente poco profundas.

Corrección: varios comentarios a continuación correctamente han señalado que no es correcto decir que el constructor de copia por defecto siempre realiza una copia superficial (o una copia en profundidad, para el caso). Si el constructor de copias de un tipo crea una copia superficial, o una copia profunda, o algo intermedio entre los dos, depende de la combinación del comportamiento de copia de cada miembro; Después de todo, se puede hacer que un constructor de copias de un miembro haga lo que quiera.

Esto es lo que la sección 12.8, párrafo 8 de la norma del 1998, C++ dice acerca de los ejemplos de código anteriores:

La definido implícitamente copia constructor para la clase X realiza una copia miembro por miembro de sus subobjetos. [...] Cada subobjeto se copia en la forma apropiada a su tipo: [...] [I] f el subobjeto es de tipo escalar, el operador de asignación incorporado se utilizado.

+1

El párrafo críptico parece estar en desacuerdo con su afirmación en negrita de que el constructor de copia predeterminado solo hace copias superficiales. – UncleBens

+0

¿Qué te hace pensar eso? Entiendo esto de la siguiente manera: los miembros de algún tipo de puntero son un subobjeto escalar, ¿no es así?Y si copia un puntero usando el operador de asignación incorporado, eso significa que el objeto apuntado no se clonará, sino que simplemente se lo referirá con un puntero adicional. Por lo tanto, terminas con una copia superficial. – stakx

+1

@stakx Tienes razón, pero creo que esto ilustra que los términos "copia profunda" y "copia superficial" no son particularmente útiles; de hecho, nunca los he escuchado usarlos por programadores expertos en C++. –

2

La copia profunda literalmente realiza una copia profunda. Significa que si su clase tiene algunos campos que son referencias, sus valores serán copiados, no referencias ellos mismos. Si, por ejemplo, tiene dos instancias de una clase, A & B con campos de tipo de referencia, y realiza una copia en profundidad, cambiar un valor de ese campo en A no afectará un valor en B. Y viceversa. Las cosas son diferentes con una copia superficial, porque solo se copian las referencias, por lo tanto, cambiar este campo en un objeto copiado afectaría al objeto original.

¿Qué tipo de copia hace un constructor de copia?

Depende de la implementación. Esto significa que no existen reglas estrictas al respecto, puede implementarlo como una copia profunda o superficial, sin embargo, hasta donde sé, es una práctica común implementar una copia profunda en un constructor de copia. Sin embargo, un constructor de copia predeterminado realiza una copia superficial.

Cuestiones relacionadas