Qual é a diferença entre uma cópia profunda e uma cópia superficial?
language-agnostic
copy
deep-copy
shallow-copy
David Locke
fonte
fonte
Respostas:
Cópias rasas duplicam o mínimo possível. Uma cópia superficial de uma coleção é uma cópia da estrutura da coleção, não dos elementos. Com uma cópia superficial, duas coleções agora compartilham os elementos individuais.
Cópias profundas duplicam tudo. Uma cópia profunda de uma coleção é composta por duas coleções com todos os elementos da coleção original duplicados.
fonte
Largura x Profundidade; pense em termos de uma árvore de referências com seu objeto como o nó raiz.
Raso:
As variáveis A e B se referem a diferentes áreas da memória, quando B é atribuído a A, as duas variáveis se referem à mesma área da memória. Modificações posteriores no conteúdo de um são refletidas instantaneamente no conteúdo de outros, à medida que compartilham o conteúdo.
Profundo:
As variáveis A e B se referem a diferentes áreas da memória, quando B é atribuído a A, os valores na área de memória que A aponta para são copiados na área de memória para a qual B aponta. Modificações posteriores no conteúdo de um permanecem exclusivas de A ou B; o conteúdo não é compartilhado.
fonte
Em resumo, depende de quais pontos apontam para o quê. Em uma cópia superficial, o objeto B aponta para a localização do objeto A na memória. Na cópia em profundidade, todas as coisas na localização da memória do objeto A são copiadas para a localização da memória do objeto B.
Este artigo wiki tem um ótimo diagrama.
http://en.wikipedia.org/wiki/Object_copy
fonte
Tente considerar a seguinte imagem
Por exemplo, Object.MemberwiseClone cria um link de cópia superficial
e usando ICloneable interface que você pode obter profunda cópia como descrito aqui
fonte
Especialmente para desenvolvedores de iOS:
Se
B
for uma cópia superficial deA
, para dados primitivos é comoB = [A assign];
e para objetos é comoB = [A retain]
;B e A apontam para o mesmo local de memória
Se
B
é uma cópia profunda deA
, é comoB = [A copy];
B e A apontam para diferentes locais de memória
O endereço de memória B é igual ao de A
B tem o mesmo conteúdo que A
fonte
Cópia rasa: copia os valores dos membros de um objeto para outro.
Cópia profunda: copia os valores dos membros de um objeto para outro.
Quaisquer objetos ponteiros são duplicados e copiados em profundidade.
Exemplo:
fonte
Eu não vi uma resposta curta e fácil de entender aqui - então vou tentar.
Com uma cópia superficial, qualquer objeto apontado pela fonte também é apontado pelo destino (para que nenhum objeto referenciado seja copiado).
Com uma cópia detalhada, qualquer objeto apontado pela fonte é copiado e a cópia é apontada pelo destino (portanto, agora haverá 2 de cada objeto referenciado). Isso ocorre novamente na árvore de objetos.
fonte
Apenas para facilitar o entendimento, você pode seguir este artigo: https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm
Cópia rasa:
Cópia profunda:
fonte
{Imagine dois objetos: A e B do mesmo tipo _t (com relação ao C ++) e você está pensando em copiar superficialmente / profundamente A para B}
Cópia superficial: Simplesmente faça uma cópia da referência de A em B. Pense nela como uma cópia do endereço de A. Portanto, os endereços de A e B serão os mesmos, ou seja, estarão apontando para o mesmo local da memória, ou seja, o conteúdo dos dados.
Cópia detalhada: Simplesmente faz uma cópia de todos os membros de A, aloca memória em um local diferente para B e depois atribui os membros copiados a B para obter uma cópia profunda. Dessa forma, se A se tornar inexistente, B ainda será válido na memória. O termo correto a ser usado seria clonagem, onde você sabe que os dois são totalmente iguais, mas ainda assim diferentes (ou seja, armazenados como duas entidades diferentes no espaço da memória). Você também pode fornecer seu wrapper de clone, onde pode decidir, por meio da lista de inclusão / exclusão, quais propriedades selecionar durante a cópia em profundidade. Essa é uma prática bastante comum quando você cria APIs.
Você pode optar por fazer uma cópia rasa ONLY_IF se entender as apostas envolvidas. Quando você tem um número enorme de ponteiros para lidar em C ++ ou C, fazer uma cópia superficial de um objeto é REALMENTE uma má idéia.
EXAMPLE_OF_DEEP COPY_ Um exemplo é que, quando você está tentando fazer o processamento de imagens e o reconhecimento de objetos, precisa mascarar "Movimento irrelevante e repetitivo" fora de suas áreas de processamento. Se você estiver usando ponteiros de imagem, poderá ter a especificação para salvar essas imagens de máscara. AGORA ... se você fizer uma cópia superficial da imagem, quando as referências do ponteiro forem KILLED da pilha, você perderá a referência e sua cópia, ou seja, haverá um erro de tempo de execução da violação de acesso em algum momento. Nesse caso, o que você precisa é de uma cópia profunda da sua imagem CLONANDO-a. Dessa forma, você pode recuperar as máscaras, caso precise delas no futuro.
EXAMPLE_OF_SHALLOW_COPY Não tenho muito conhecimento em comparação com os usuários do StackOverflow, portanto, sinta-se à vontade para excluir esta parte e dar um bom exemplo, se puder esclarecer. Mas eu realmente acho que não é uma boa idéia fazer uma cópia superficial se você souber que seu programa será executado por um período infinito de tempo, isto é, operação contínua de "push-pop" sobre a pilha com chamadas de função. Se você está demonstrando algo para uma pessoa amadora ou iniciante (por exemplo, material tutorial em C / C ++), provavelmente está tudo bem. Mas se você estiver executando um aplicativo, como um sistema de vigilância e detecção, ou o Sonar Tracking System, não deverá copiar superficialmente seus objetos, pois isso matará seu programa mais cedo ou mais tarde.
fonte
'ShallowCopy' aponta para o mesmo local na memória que 'Source'. 'DeepCopy' aponta para um local diferente na memória, mas o conteúdo é o mesmo.
fonte
O que é cópia rasa?
Cópia rasa é uma cópia em bits de um objeto. Um novo objeto é criado com uma cópia exata dos valores no objeto original. Se qualquer um dos campos do objeto for referência a outros objetos, apenas os endereços de referência serão copiados, ou seja, somente o endereço de memória será copiado.
Nesta figura, os
MainObject1
campos temfield1
do tipo int eContainObject1
do tipoContainObject
. Quando você faz uma cópia superficial deMainObject1
,MainObject2
é criadafield2
contendo o valor copiadofield1
e ainda apontando paraContainObject1
si mesma. Observe que, comofield1
é do tipo primitivo, seu valor é copiado para,field2
mas comoContainedObject1
é um objeto,MainObject2
ainda aponta paraContainObject1
. Portanto, quaisquer alterações feitas noContainObject1
inMainObject1
serão refletidasMainObject2
.Agora, se essa é uma cópia superficial, vamos ver o que é cópia profunda?
O que é cópia profunda?
Uma cópia profunda copia todos os campos e faz cópias da memória alocada dinamicamente, apontada pelos campos. Uma cópia profunda ocorre quando um objeto é copiado junto com os objetos aos quais se refere.
Nesta figura, o MainObject1 possui campos
field1
do tipo int eContainObject1
do tipoContainObject
. Quando você faz uma cópia profunda deMainObject1
,MainObject2
é criadofield2
contendo o valor copiado defield1
eContainObject2
contendo o valor copiado deContainObject1
. Observe que quaisquer alterações feitas emContainObject1
inMainObject1
não serão refletidas emMainObject2
.bom artigo
fonte
field3
que, em posição de tentar compreender algo tão profundo quanto esse problema, onde está ocorrendo o número 3 desse exemploContainObject2
?Na programação orientada a objetos, um tipo inclui uma coleção de campos membros. Esses campos podem ser armazenados por valor ou por referência (ou seja, 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 como os valores. Portanto, as referências estão apontando para os objetos originais. Quaisquer alterações nos membros que são armazenadas por referência aparecem no original e na cópia, já que nenhuma cópia foi feita do objeto referenciado.
Em uma cópia detalhada, os campos armazenados por valor são copiados como antes, mas os ponteiros para objetos armazenados por referência não são copiados. Em vez disso, é feita uma cópia profunda do objeto referenciado e um ponteiro para o novo objeto é armazenado. Quaisquer alterações feitas nos objetos referenciados não afetarão outras cópias do objeto.
fonte
'ShallowCopy' aponta para o mesmo local na memória que 'Source'. 'DeepCopy' aponta para um local diferente na memória, mas o conteúdo é o mesmo.
fonte
Clonagem
rasa : Definição: "Uma cópia superficial de um objeto copia o objeto 'principal', mas não copia os objetos internos." Quando um objeto personalizado (por exemplo, Employee) possui variáveis primitivas do tipo String, você usa a Clonagem rasa.
Você retorna
super.clone();
no método clone () substituído e seu trabalho termina.Clonagem Profunda :
Definição: "Ao contrário da cópia superficial, uma cópia profunda é uma cópia totalmente independente de um objeto".
Significa quando um objeto Employee mantém outro objeto customizado:
Então você deve escrever o código para clonar o objeto 'Address' também no método clone () substituído. Caso contrário, o objeto Address não será clonado e causará um erro quando você alterar o valor de Address no objeto Employee clonado, o que reflete o original também.
fonte
fonte
Cópia profunda
Uma cópia profunda copia todos os campos e faz cópias da memória alocada dinamicamente, apontada pelos campos. Uma cópia profunda ocorre quando um objeto é copiado junto com os objetos aos quais se refere.
Cópia rasa
Cópia rasa é uma cópia em bits de um objeto. Um novo objeto é criado com uma cópia exata dos valores no objeto original. Se algum dos campos do objeto for referência a outros objetos, apenas os endereços de referência serão copiados, ou seja, somente o endereço de memória será copiado.
fonte
Cópia rasa - A variável de referência dentro dos objetos originais e copiados em pouca profundidade tem referência ao objeto comum .
Cópia Profunda - A variável de referência dentro de objetos originais e copiados em profundidade tem referência a objetos diferentes .
classe principal está seguindo-
O resultado acima será
Qualquer alteração feita no objeto original irá refletir no objeto raso e não no objeto profundo.
OutPut- ViSuaLBaSiC C
fonte
Eu gostaria de dar um exemplo, e não a definição formal.
Este código mostra uma cópia superficial :
Este código mostra uma cópia detalhada :
fonte
1 1 4 4 4 4 4 4
fonte
Em termos simples, uma cópia rasa é semelhante a chamada por referência e uma cópia profunda é semelhante a chamada por valor
Em Chamada por referência, os parâmetros formais e reais de uma função se referem ao mesmo local de memória e ao valor.
Em Chamada por valor, os parâmetros formais e reais de uma função se referem a um local de memória diferente, mas com o mesmo valor.
fonte
Imagine que existem duas matrizes chamadas arr1 e arr2.
fonte
Uma cópia superficial constrói um novo objeto composto e insere suas referências ao objeto original.
Diferentemente da cópia superficial, a cópia em profundidade constrói o novo objeto composto e também insere cópias dos objetos originais do objeto composto original.
Vamos dar um exemplo.
O código acima imprime FALSE.
Vamos ver como.
Objeto composto original
x=[1,[2]]
(chamado como composto porque possui objeto dentro do objeto (Inception))como você pode ver na imagem, há uma lista dentro da lista.
Em seguida, criamos uma cópia superficial usando
y = copy.copy(x)
. O que o python faz aqui é: ele criará um novo objeto composto, mas os objetos dentro deles estão apontando para os objetos originais.Na imagem, ele criou uma nova cópia para a lista externa. mas a lista interna permanece a mesma da lista original.
Agora criamos uma cópia em profundidade dele usando
z = copy.deepcopy(x)
. o que o python faz aqui é, ele criará um novo objeto para a lista externa e a lista interna. como mostrado na imagem abaixo (destacado em vermelho).No final, o código é impresso
False
, pois y e z não são os mesmos objetos.HTH.
fonte
A cópia rasa é criar um novo objeto e, em seguida, copiar os campos não estáticos do objeto atual para o novo objeto. Se um campo for um tipo de valor -> é executada uma cópia bit a bit do campo; 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.
A cópia profunda está criando um novo objeto e, em seguida, copiando os campos não estáticos do objeto atual para o novo objeto. Se um campo é um tipo de valor -> é executada uma cópia bit a bit do campo. Se um campo for um tipo de referência -> uma nova cópia do objeto referido será executada. As classes a serem clonadas devem ser sinalizadas como [Serializable].
fonte
Retirado de [blog]: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html
A cópia profunda envolve o uso do conteúdo de um objeto para criar outra instância da mesma classe. Em uma cópia detalhada, os dois objetos podem conter as mesmas informações, mas o objeto de destino terá seus próprios buffers e recursos. a destruição de qualquer objeto não afetará o objeto restante. O operador de atribuição sobrecarregado criaria uma cópia profunda dos objetos.
Cópia rasa envolve copiar o conteúdo de um objeto em outra instância da mesma classe, criando assim uma imagem espelhada. Devido à cópia direta de referências e ponteiros, os dois objetos compartilharão o mesmo conteúdo externo do outro objeto, de forma imprevisível.
Explicação:
Usando um construtor de cópia, simplesmente copiamos os valores dos dados membro por membro. Esse método de cópia é chamado de cópia superficial. Se o objeto for uma classe simples, composta de tipos incorporados e sem ponteiros, isso seria aceitável. Essa função usaria os valores e os objetos e seu comportamento não seria alterado com uma cópia superficial, apenas os endereços dos ponteiros que são membros são copiados e não o valor para o qual o endereço está apontando. Os valores dos dados do objeto seriam alterados inadvertidamente pela função. Quando a função sai do escopo, a cópia do objeto com todos os seus dados é removida da pilha.
Se o objeto tiver ponteiros, é necessário executar uma cópia profunda. Com a cópia profunda de um objeto, a memória é alocada para o objeto no armazenamento gratuito e os elementos apontados são copiados. Uma cópia detalhada é usada para objetos retornados de uma função.
fonte
Para adicionar mais a outras respostas,
fonte
A cópia rasa não criará nova referência, mas a cópia profunda criará a nova referência.
Aqui está o programa para explicar a cópia profunda e superficial.
fonte
Copiando ararys:
Matriz é uma classe, o que significa que é o tipo de referência; portanto, matriz1 = matriz2 resulta em duas variáveis que referenciam a mesma matriz.
Mas veja este exemplo:
clone superficial significa que apenas a memória representada pela matriz clonada é copiada.
Se a matriz contiver objetos do tipo valor, os valores serão copiados ;
se a matriz contiver um tipo de referência, apenas as referências serão copiadas. Portanto, existem duas matrizes cujos membros fazem referência aos mesmos objetos .
Para criar uma cópia detalhada - onde o tipo de referência é duplicado, você deve percorrer a matriz e clonar cada elemento manualmente.
fonte
private void button1_Click(object sender, EventArgs e) { int[] arr1 = new int[]{1,2,3,4,5}; int[] arr2 = new int[]{6,7,8,9,0}; MessageBox.Show(arr1[2] + " " + arr2[2]); arr2 = arr1; MessageBox.Show(arr1[2] + " " + arr2[2]); arr1[2] = 12; MessageBox.Show(arr1[2] + " " + arr2[2]); }
Eu vim a entender das seguintes linhas.
A cópia rasa copia um tipo de valor do objeto (int, float, bool) nos campos para o objeto de destino e os tipos de referência do objeto (string, classe etc.) são copiados como referências no objeto de destino. Nesse destino, os tipos de referência apontam para o local da memória do objeto de origem.
A cópia profunda copia o valor e os tipos de referência de um objeto em uma nova cópia completa dos objetos de destino. Isso significa que os tipos de valor e de referência receberão novos locais de memória.
fonte
Adicionando a todas as definições acima, uma cópia profunda mais comumente usada, está no construtor de cópias (ou oprator de atribuição de sobrecarga) da classe.
Cópia rasa -> é quando você não fornece um construtor de cópias. Aqui, apenas o objeto é copiado, mas nem todos os membros da classe são copiados.
Cópia profunda -> é quando você decide implementar o construtor de cópias ou a atribuição de sobrecarga em sua classe e permite copiar todos os membros da classe.
fonte
O construtor de cópia é usado para inicializar o novo objeto com o objeto criado anteriormente da mesma classe. Por padrão, o compilador escreveu uma cópia superficial. A cópia rasa funciona bem quando a alocação dinâmica de memória não está envolvida porque, quando a alocação dinâmica de memória está envolvida, os dois objetos apontam para o mesmo local da memória em um heap. Portanto, para remover esse problema, escrevemos uma cópia profunda para que os dois objetos tenham sua própria cópia dos atributos em uma memória. Para ler os detalhes com exemplos e explicações completos, você pode ver o artigo Construtores C ++ .
fonte