Pergunta

O que é a diferença entre uma cópia profunda e uma cópia superficial?

Foi útil?

Solução

cópias rasas duplicar o mínimo possível. Uma cópia superficial de uma colecção é uma cópia da estrutura de recolha, não os elementos. Com uma cópia superficial, duas coleções agora compartilham os elementos individuais.

cópias de profundidade duplicar tudo. Uma cópia em profundidade de uma coleção é duas coleções com todos os elementos da coleção original duplicado.

Outras dicas

Amplitude vs Profundidade; pensar em termos de uma árvore de referências com o seu objeto como o nó raiz.

Shallow:

Antes de Copiar Copiar raso Shallow Feito

As variáveis ??A e B referem-se a diferentes áreas da memória, quando B é atribuído a uma das duas variáveis ??se referem à mesma área de memória. modificações posteriores ao conteúdo de ambos são instantaneamente refletida no conteúdo de outro, como eles compartilham conteúdo.

Deep:

Antes de Copiar Copiar Deep Deep Feito

As variáveis ??A e B referem-se a diferentes áreas da memória, quando B é atribuído a um dos valores na área de memória que os pontos à são copiados para a área de memória para que os pontos B. modificações posteriores ao conteúdo ou permanecer exclusivo para A ou B; os conteúdos não são compartilhados.

Em suma, isso depende do que pontos para o quê. Em uma cópia superficial, pontos objeto B se opor a localização de uma na memória. Na cópia profunda, todas as coisas na localização do objeto memória de um ser copiado ao local de memória objeto de B.

Este artigo wiki tem um grande diagrama.

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

Especialmente para iOS Developers:

Se B é um cópia superficial de A, em seguida, para os dados primitivos é como B = [A assign]; e para objetos é como B = [A retain];

B e um ponto para o local mesma memória

Se B é um cópia profunda de A, então é como B = [A copy];

B e um ponto para diferentes posições de memória

endereço de memória B é a mesma de A

B tem o mesmo conteúdo como de A

Tente considerar seguinte imagem

 enter descrição da imagem aqui

Por exemplo Object.MemberwiseClone cria um rasa cópia link

e usando ICloneable Interface você pode obter profunda copiar como descrito aqui

cópia superficial:. Copia os valores de membro de um objeto em outro

Deep Cópia:. Copia os valores de membro de um objeto em outro
Todos os objetos ponteiro são duplicados e Deep copiado.

Exemplo:

class String
{
     int   size;
     char* data;
};

String  s1("Ace");   // s1.size = 3 s1.data=0x0000F000

String  s2 = shallowCopy(s1);
 // s2.size =3 s2.data = 0X0000F000
String  s3 = deepCopy(s1);
 // s3.size =3 s3.data = 0x0000F00F
 //                      (With Ace copied to this location.)

Eu não vi um curto, fácil de entender resposta aqui -. Por isso vou dar-lhe uma tentativa

Com uma cópia superficial, qualquer objeto apontado pela fonte também é apontado pelo destino (de modo que não existem objectos referenciados são copiados).

Com uma cópia profunda, qualquer objeto apontado pela fonte é copiado e a cópia é apontado pelo destino (assim haverá agora 2 de cada objeto referenciado). Este recurses para baixo a árvore de objetos.

Apenas por uma questão de compreensão fácil você poderia seguir este artigo: https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying. htm


rasa Copiar:

Shallow copy


Deep Cópia:

Deep copy

{Imagine que dois objetos: A e B do mesmo tipo _t (com respeito a C ++) e você está pensando sobre a rasa / cópia profunda A para B}

rasa Copiar: Simplesmente faz uma cópia da referência a A em B. Pense nisso como uma cópia de um endereço. Assim, os endereços de A e B será o mesmo ou seja, eles vão estar apontando para o mesmo local de memória ou seja, conteúdo de dados.

cópia Deep: Simplesmente faz uma cópia de todos os membros de A, aloca memória em um local diferente para B e, em seguida, atribui os membros copiado para B para alcançar cópia profunda. Desta forma, se um se torna inexistente B ainda é válido na memória. O termo correto para uso seria clonagem, onde você sabe que ambos são totalmente o mesmo, mas ainda diferente (ou seja armazenada como duas entidades diferentes no espaço de memória). Você também pode fornecer seu wrapper clone onde você pode decidir por meio de lista de inclusão / exclusão que propriedades para selecionar durante a cópia profunda. Isto é bastante uma prática comum quando você cria APIs.

Você pode optar por fazer uma rasa Copiar ONLY_IF você entende os riscos envolvidos. Quando você tem grande número de ponteiros para lidar com em C ++ ou C, fazendo uma cópia superficial de um objeto é realmente uma má idéia.

EXAMPLE_OF_DEEP COPY _ Um exemplo é, quando você está tentando fazer processamento de imagens e reconhecimento de objetos que você precisa para mascarar "irrelevante e repetitivo movimento" fora de suas áreas de processamento. Se você estiver usando ponteiros imagem, então você pode ter a especificação para salvar essas imagens máscara. AGORA ... se você fizer uma cópia superficial da imagem, quando as referências de ponteiro são mortos a partir da pilha, você perdeu a referência e sua cópia ou seja, haverá um erro de execução de violação de acesso em algum ponto. Neste caso, o que você precisa é uma cópia profunda de sua imagem por clonagem-lo. Desta forma, você pode recuperar as máscaras no caso de você precisar deles no futuro.

EXAMPLE_OF_SHALLOW_COPY Eu não sou extremamente bem em comparação com os usuários em StackOverflow tão à vontade para excluir esta parte e colocar um bom exemplo se você pode esclarecer. Mas eu realmente acho que não é uma boa idéia para fazer cópia superficial se você sabe que seu programa é vai correr por um período de tempo infinito ou seja contínua operação "push-pop" sobre a pilha com chamadas de função. Se você está demonstrando algo a uma pessoa amador ou iniciante (por exemplo, C / C ++ material tutorial), então ele é provavelmente bem. Mas se você estiver executando um aplicativo como o sistema de vigilância e detecção, ou Sonar Sistema de Rastreamento, você não é suposto para manter rasa copiar seus objetos ao redor, porque ele vai matar o seu programa mais cedo ou mais tarde.

char * Source = "Hello, world.";

char * ShallowCopy = Source;    

char * DeepCopy = new char(strlen(Source)+1);
strcpy(DeepCopy,Source);        

'ShallowCopy' aponta para o mesmo local na memória como 'Fonte' faz. 'deepcopy' aponta para um local diferente em memória, mas o conteúdo é o mesmo.

O que é raso Cópia?

cópia superficial é uma cópia de um objeto bit-wise. Um novo objeto é criado que tem uma cópia exata dos valores no objeto original. Se qualquer um dos campos do objeto são referências a outros objetos, apenas os endereços de referência são copiados ou seja, somente o endereço de memória é copiado. Shallow Copy

Nesta figura, o MainObject1 tem campos field1 do tipo int, e ContainObject1 do tipo ContainObject. Quando você faz uma cópia superficial do MainObject1, MainObject2 é criado com field2 contendo o valor copiado de field1 e ainda apontando para ContainObject1 si. Note-se que desde field1 é do tipo primitivo, o seu valor é copiado para field2 mas desde ContainedObject1 é um objeto, MainObject2 ainda aponta para ContainObject1. Assim, quaisquer alterações feitas ContainObject1 em MainObject1 será refletido no MainObject2.

Agora, se esta é cópia superficial, vamos ver o que é cópia profunda?

O que é profunda Cópia?

Uma cópia profunda copia todos os campos, e faz cópias de memória alocada dinamicamente apontado pelo campos. Uma cópia profunda ocorre quando um objeto é copiado juntamente com os objetos a que se refere. Deep Copy

Nesta figura, os MainObject1 têm campos field1 do tipo int, e ContainObject1 do tipo ContainObject. Quando você faz uma cópia profunda MainObject1, MainObject2 é criado com field2 contendo o valor copiado de field1 e ContainObject2 contendo o valor copiado de ContainObject1. Nota quaisquer alterações feitas ContainObject1 em MainObject1 não refletirá em MainObject2.

bom artigo

Na programação orientada a objeto, um tipo inclui uma coleção de campos membros. Estes campos podem ser armazenados por valor ou por referência (isto é, um ponteiro para um valor).

Em uma cópia superficial, uma nova instância do tipo é criada e os valores são copiados para a nova instância. Os ponteiros de referência também são copiados assim como os valores. Portanto, as referências estão apontando para os objetos originais. Quaisquer alterações aos membros que estão armazenados por referência aparecem tanto o original ea cópia, uma vez que nenhuma cópia foi feita do objeto referenciado.

Em uma cópia em profundidade, os campos que são armazenados pelo valor são copiados como antes, mas os ponteiros para objetos armazenados por referência não são copiadas. Em vez disso, uma cópia profunda é feita do objeto referenciado, e um ponteiro para o novo objeto é armazenado. Quaisquer alterações que são feitas para os objetos referenciados não afetará outras cópias do objeto.

'ShallowCopy' aponta para o mesmo local na memória como 'Fonte' faz. 'deepcopy' aponta para um local diferente em memória, mas o conteúdo é o mesmo.

var source = { firstName="Jane", lastname="Jones" };
var shallow = ShallowCopyOf(source);
var deep = DeepCopyOf(source);
source.lastName = "Smith";
WriteLine(source.lastName); // prints Smith
WriteLine(shallow.lastName); // prints Smith
WriteLine(deep.lastName); // prints Jones

Clonagem Shallow:
Definição: "Uma cópia superficial de um objeto copia o‘principal’objeto, mas não copia os objetos internos." Quando um objeto personalizado (ex. Employee) acaba primitivo, variáveis ??tipo string, então você usar Clonagem raso.

Employee e = new Employee(2, "john cena");
Employee e2=e.clone();

Você retorna super.clone(); no método clone () substituído e seu trabalho é longo.

Deep Clonagem :
Definição: "Ao contrário da cópia superficial, uma cópia profunda é uma cópia totalmente independente de um objeto."
Significa que quando um objeto Employee detém outro objeto personalizado:

Employee e = new Employee(2, "john cena", new Address(12, "West Newbury", "Massachusetts");

Em seguida, você tem que escrever o código para clonar o objeto 'Endereço', bem como no método clone () substituído. Caso contrário, o objeto Address não será clone e faz com que um erro quando você alterar o valor de endereço em clonado Employee objeto, o que reflete o original também.

Deep Copiar

Uma cópia profunda copia todos os campos, e faz cópias de memória alocada dinamicamente apontado pelo campos. Uma cópia profunda ocorre quando um objeto é copiado juntamente com os objetos a que se refere.

rasa Copiar

cópia superficial é uma cópia de um objeto bit-wise. Um novo objeto é criado que tem uma cópia exata dos valores no objeto original. Se qualquer um dos campos do objeto são referências a outros objetos, apenas os endereços de referência são copiados ou seja, somente o endereço de memória é copiado.

rasa Copiar -. Variável de referência dentro de objetos originais e copiados-rasas tem referência a comum objeto

Deep Copiar -. Variável de referência dentro de objetos originais e deep-copiados tem referência a diferente objeto

clone sempre faz cópia superficial.

public class Language implements Cloneable{

    String name;
    public Language(String name){
        this.name=name;
    }

    public String getName() {
        return name;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

classe principal está seguindo -

public static void main(String args[]) throws ClassNotFoundException, CloneNotSupportedException{

      ArrayList<Language> list=new ArrayList<Language>();
      list.add(new Language("C"));
      list.add(new Language("JAVA"));

      ArrayList<Language> shallow=(ArrayList<Language>) list.clone();
      //We used here clone since this always shallow copied.

      System.out.println(list==shallow);

      for(int i=0;i<list.size();i++)
      System.out.println(list.get(i)==shallow.get(i));//true

      ArrayList<Language> deep=new ArrayList<Language>();
      for(Language language:list){
          deep.add((Language) language.clone());
      }
      System.out.println(list==deep);
      for(int i=0;i<list.size();i++)
          System.out.println(list.get(i)==deep.get(i));//false

} 

saída acima será -

false true true

false false false

Qualquer mudança feita no objeto original irá refletir no objeto rasa não em profunda objeto.

  list.get(0).name="ViSuaLBaSiC";
  System.out.println(shallow.get(0).getName()+"  "+deep.get(0).getName());

Saída - VisualBasic C

Eu gostaria de dar exemplo, em vez da definição formal.

var originalObject = { 
    a : 1, 
    b : 2, 
    c : 3,
};

mostra este código a cópia superficial :

var copyObject1 = originalObject;

console.log(copyObject1.a);         // it will print 1 
console.log(originalObject.a);       // it will also print 1 
copyObject1.a = 4; 
console.log(copyObject1.a);           //now it will print 4 
console.log(originalObject.a);       // now it will also print 4

var copyObject2 = Object.assign({}, originalObject);

console.log(copyObject2.a);        // it will print 1 
console.log(originalObject.a);      // it will also print 1 
copyObject2.a = 4; 
console.log(copyObject2.a);        // now it will print 4 
console.log(originalObject.a);      // now it will print 1

mostra este código a cópia profunda :

var copyObject2 = Object.assign({}, originalObject);

console.log(copyObject2.a);        // it will print 1 
console.log(originalObject.a);      // it will also print 1 
copyObject2.a = 4; 
console.log(copyObject2.a);        // now it will print 4 
console.log(originalObject.a);      // !! now it will print 1 !!
struct sample
{
    char * ptr;
}
void shallowcpy(sample & dest, sample & src)
{
    dest.ptr=src.ptr;
}
void deepcpy(sample & dest, sample & src)
{
    dest.ptr=malloc(strlen(src.ptr)+1);
    memcpy(dest.ptr,src.ptr);
}

Em termos simples, uma rasa Copiar é semelhante à chamada por referência e uma cópia profunda é semelhante a Chamada por Valor

Ambos os parâmetros formais e reais de uma função Na chamada por referência, refere-se a mesma posição de memória e o valor.

Em Chamada por valor, Ambos os parâmetros formais e reais de uma série de funções refere-se a diferente posição de memória, mas tendo o mesmo valor.

Imagine que existem duas matrizes chamados arr1 e ARR2.

arr1 = arr2;   //shallow copy
arr1 = arr2.clone(); //deep copy

Shallow a cópia está criando um novo objeto e, em seguida, copiar os campos não-estático do objeto atual para o novo objeto. Se um campo é um tipo de valor -> uma cópia bit a bit do campo é realizada; para um tipo de referência -> a referência é copiada, mas o objeto referido não é; portanto, o objeto original e seu clone se referem ao mesmo objeto.

Deep cópia é a criação de um novo objeto e, em seguida, copiar os campos não estática do objeto atual para o novo objeto. Se um campo é um tipo valor -> é realizada uma cópia bit a bit do campo. Se um campo é um tipo referência -> é realizada uma nova cópia do objeto a que se refere. As classes a serem clonados deve ser sinalizado como [Serializable].

Tomado de [do blog]: http: // sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

cópia profunda envolve usando o conteúdo de um objeto para criar outra instância da mesma classe. Em uma cópia em profundidade, os dois objetos podem conter ht mesma informação, mas o objeto de destino terá os seus próprios buffers e recursos. a destruição de qualquer objecto não vai afectar o objecto remanescente. O operador de atribuição sobrecarregado criaria uma cópia em profundidade de objetos.

cópia superficial envolve copiar o conteúdo de um objeto em outra instância da mesma classe, criando assim uma imagem de espelho. Devido à cópia reta de referências e ponteiros, os dois objetos irão compartilhar os mesmos conteúdos contidos externamente de outro objeto a ser imprevisível.

Explicação:

Usando um construtor de cópia nós simplesmente copiar o membro valores dados pelos Estados. Este método de cópia é chamado de cópia superficial. Se o objeto é uma classe simples, composto de construído em tipos e sem ponteiros isso seria aceitável. Esta função seria utilizar os valores e os objetos e seu comportamento não seria alterada com uma cópia superficial, apenas os endereços de ponteiros que são membros são copiados e não o valor do endereço está apontando. Os valores de dados do objecto seria, em seguida, ser inadvertidamente alteradas pela função. Quando a função sai do escopo, a cópia do objeto com todos os seus dados é retirado da pilha.

Se o objeto tem qualquer ponteiros uma cópia profunda precisa ser executado. Com a cópia em profundidade de um objeto, a memória é alocada para o objeto na loja livre e os elementos apontada são copiados. Uma cópia profunda é usado para objetos que são devolvidos a partir de uma função.

Para adicionar mais para outras respostas,

  • a Shallow cópia de um objeto executa cópia por valor para tipos de valor propriedades com base, e da cópia de referência para tipos de referência propriedades com base.
  • Uma profunda cópia de um objeto executa cópia por valor para tipos de valor com base propriedades, bem como cópia de valor para tipos de referência baseado Propriedades profundo na hierarquia (de tipos de referência)

A cópia superficial constrói um novo objeto composto e inserir suas referências para ela, para o objeto original.

cópia superficial Ao contrário, as construções de deepcopy novo composto objecto também e insere cópias dos objectos originais original é objecto composto.

Vamos dar um exemplo.

import copy
x =[1,[2]]
y=copy.copy(x)
z= copy.deepcopy(x)
print(y is z)

Acima de impressões código FALSE.

Vamos ver como.

x=[1,[2]] composto objeto original (chamado como composto porque tem objeto dentro do objeto (Inception))

enter descrição da imagem aqui

como você pode ver na imagem, há uma lista lista dentro.

Então vamos criar uma cópia superficial do que usando y = copy.copy(x). O que Python faz aqui é, ele irá criar um novo objeto composto, mas objetos dentro deles estão apontando para os objetos orignal.

enter descrição da imagem aqui

Na imagem que criou uma nova cópia de lista externa. mas a lista interna permanece mesmo que o original.

Agora vamos criar deepcopy dele usando z = copy.deepcopy(x). o python faz aqui é, ele irá criar novo objeto para a lista exterior, bem como a lista interna. como mostrado na imagem abaixo (vermelho realçado).

enter descrição da imagem aqui

No gravuras código final False, como Y e Z não são mesmos objectos.

HTH.

cópia superficial não vai criar nova referência, mas cópia profunda irá criar a nova referência.

Aqui está o programa para explicar a cópia profunda e superficial.

public class DeepAndShollowCopy {
    int id;
    String name;
    List<String> testlist = new ArrayList<>();

    /*
    // To performing Shallow Copy 
    // Note: Here we are not creating any references. 
      public DeepAndShollowCopy(int id, String name, List<String>testlist)
       { 

       System.out.println("Shallow Copy for Object initialization");
       this.id = id; 
       this.name = name; 
       this.testlist = testlist; 

       }
    */  

    // To performing Deep Copy 
    // Note: Here we are creating one references( Al arraylist object ). 
    public DeepAndShollowCopy(int id, String name, List<String> testlist) {
        System.out.println("Deep Copy for Object initialization");
        this.id = id;
        this.name = name;
        String item;
        List<String> Al = new ArrayList<>();
        Iterator<String> itr = testlist.iterator();
        while (itr.hasNext()) {
            item = itr.next();
            Al.add(item);
        }
        this.testlist = Al;
    }


    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Oracle");
        list.add("C++");
        DeepAndShollowCopy copy=new DeepAndShollowCopy(10,"Testing", list);
        System.out.println(copy.toString());
    }
    @Override
    public String toString() {
        return "DeepAndShollowCopy [id=" + id + ", name=" + name + ", testlist=" + testlist + "]";
    }
}

Copiar ararys:

matriz é uma classe, o que significa que é o tipo de referência, de modo matriz1 = array2 resultados em duas variáveis ??que se referem a mesma matriz.

Mas olhar para este exemplo:

  static void Main()
    {
        int[] arr1 = new int[] { 1, 2, 3, 4, 5 }; 
        int[] arr2 = new int[] { 6, 7, 8, 9, 0 };

        Console.WriteLine(arr1[2] + " " + arr2[2]);
        arr2 = arr1;
        Console.WriteLine(arr1[2] + " " + arr2[2]); 
        arr2 = (int[])arr1.Clone();
        arr1[2] = 12;
        Console.WriteLine(arr1[2] + " " + arr2[2]);
    }

rasa clone significa que apenas a memória representados pela matriz clonado é copiado.

Se a matriz contém objetos tipo de valor, os valores são copiados ;

se a matriz contém tipo de referência, apenas as referências são copiados - assim como um resultado há duas matrizes cujos membros referenciar os mesmos objetos .

Para criar uma onde cópia do tipo profundo de referência são duplicados, você deve percorrer a matriz e clone cada elemento manualmente.

Adicionando a todos as definições acima, mais um e mais comumente usado cópia profunda, está no construtor de cópia (ou sobrecarga oprator atribuição) da classe.

cópia superficial -> é quando você não está fornecendo construtor de cópia. Aqui, apenas o objeto é copiado, mas nem todos os membros da classe são copiados.

cópia profunda -.> É quando você decidiu implementar construtor de cópia ou cessão de sobrecarga em sua classe e permite copiar todos os membros da classe

MyClass& MyClass(const MyClass& obj) // copy constructor for MyClass
{
          // write your code, to copy all the members and return the new object
}
MyClass& operator=(const MyClass& obj) // overloading assignment operator,
{
          // write your code, to copy all the members and return the new object
}

O construtor de cópia é usado para inicializar o novo objeto com o objeto criado anteriormente da mesma classe. Pelo compilador padrão escreveu uma cópia superficial. cópia superficial funciona bem quando alocação dinâmica de memória não está envolvido porque quando alocação dinâmica de memória está envolvido em seguida, ambos os objetos serão aponta para o mesmo local de memória em uma pilha, Portanto, para remover esse problema que escreveu cópia profunda para que ambos os objetos têm a sua própria cópia de atributos em uma memória. Para ler os detalhes com exemplos completos e explicações você poderia ver o artigo C ++ construtores .

Para adicionar um pouco mais de confusão entre cópia superficial e simplesmente atribuir um novo nome de variável para lista.

"Say temos:

x = [
    [1,2,3],
    [4,5,6],
    ]

Esta declaração cria 3 listas: 2 listas internas e uma lista exterior. Uma referência à lista exterior é então disponibilizado sob o nome de x. Se fizermos

y = x

nenhum dado é copiado. Nós ainda temos os mesmos 3 listas em algum lugar da memória. Tudo isso fez é fazer a lista externa disponível sob o nome y, além de seu nome anterior x. Se fizermos

y = list(x)

ou

y = x[:]

Isso cria uma nova lista com o mesmo conteúdo que x. Lista x continha uma referência aos 2 listas internas, de modo a nova lista também conterá uma referência a esses mesmos 2 listas internas. Apenas uma lista é copiado-a lista externa. Agora, existem 4 lista na memória, as duas listas internas, a lista externa, ea cópia da lista externa. A lista externa original está disponível sob o nome x, e a nova lista exterior é feito disponível sob o nome y.

As listas internas não foram copiados! Você pode acessar e editar as listas internas de x ou y, neste ponto!

Se você tem uma lista dimensional (ou superior) dois, ou qualquer tipo de estrutura de dados aninhada, e você quer fazer uma cópia completa de tudo, então você quer usar a função deepcopy () no módulo de cópia. Sua solução também funciona para listas 2-D, como itera sobre os itens na lista externa e faz uma cópia de cada um deles, em seguida, constrói uma nova lista externa para todas as cópias internas. "

Fonte: https://www.reddit.com/r/ learnpython / comentários / 1afldr / why_is_copying_a_list_so_damn_difficult_in_python /

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top