Cópia profunda vs cópia raso

Duplicar Possível:
Qual é a diferença entre uma cópia detalhada e uma cópia superficial?

Qual é a diferença entre cópia profunda e superficial. Que tipo de cópia faz um construtor de cópias?

Cópia superficial:

Alguns membros da cópia podem fazer referência aos mesmos objects que o 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) { } }; 

Aqui, o membro pi do object X original e copiado apontará para o mesmo int .


Cópia profunda:

Todos os membros do original são clonados (recursivamente, se necessário). Não há objects compartilhados:

 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! { } }; 

Aqui, o membro pi do object X original e copiado apontará para diferentes objects int , mas ambos possuem o mesmo valor.


O construtor de cópia padrão (que é fornecido automaticamente se você não fornecer um por conta própria) cria apenas cópias superficiais.

Correção: Vários comentários abaixo apontaram corretamente que é errado dizer que o construtor de cópia padrão sempre executa uma cópia superficial (ou uma cópia profunda, para essa matéria). Se o construtor de cópia de um tipo cria uma cópia superficial, ou uma cópia profunda, ou algo entre os dois , depende da combinação do comportamento de cópia de cada membro; o construtor de cópia de um membro pode fazer o que quiser, afinal de contas.

Aqui está o que a seção 12.8, parágrafo 8 da norma C ++ de 1998 diz sobre os exemplos de código acima:

O construtor de cópia definido implicitamente para a class X executa uma cópia integrante de seus sub-objects. [...] Cada subobject é copiado da maneira apropriada ao seu tipo: [...] [I] f o subobject é do tipo escalar, o operador de atribuição embutido é usado.

O exemplo quintessencial disso é uma matriz de pointers para estruturas ou objects (que são mutáveis).

Uma cópia superficial copia a matriz e mantém referências aos objects originais.

Uma cópia em profundidade copia (clona) os objects também para que não tenham relação com o original. Implícito nisso é que o object em si é copiado em profundidade. É aí que fica difícil porque não existe uma maneira real de saber se algo foi copiado ou não.

O construtor de cópia é usado para inicializar o novo object com o object criado anteriormente da mesma class. Por padrão, o compilador escreveu uma cópia superficial. A cópia superficial funciona bem quando a alocação de memory dinâmica não está envolvida, porque quando a alocação de memory dinâmica está envolvida, ambos os objects apontarão para a mesma localização de memory em uma pilha. Portanto, para remover esse problema, escrevemos a cópia profunda para que os dois objects tenham sua própria cópia de atributos em uma memory.

Para ler os detalhes com exemplos completos e explicações, você pode ver o artigo Construtores e destruidores .

O construtor de cópia padrão é superficial. Você pode tornar seus próprios construtores de cópia profundos ou superficiais, conforme apropriado. Veja C ++ Notes: OOP: Copy Constructors .

Cópia profunda literalmente executa uma cópia profunda. Isso significa que, se a sua class tiver alguns campos que são referências, seus valores serão copiados, e não as próprias referências. Se, por exemplo, você tiver duas instâncias de uma class, A e B com campos de tipo de referência e executar uma cópia profunda, alterar um valor desse campo em A não afetará um valor em B. E vice-versa. As coisas são diferentes com a cópia superficial, porque somente referências são copiadas, portanto, alterar esse campo em um object copiado afetaria o object original.

Que tipo de cópia faz um construtor de cópias?

É dependente de implementação. Isso significa que não há regras estritas sobre isso, você pode implementá-lo como uma cópia profunda ou cópia superficial, no entanto, até onde eu saiba, é uma prática comum implementar uma cópia profunda em um construtor de cópia. Um construtor de cópia padrão executa uma cópia superficial embora.