2010-04-17 1 views
45

Eventuali duplicati:
What is the difference between a deep copy and a shallow copy?copia profonda vs copia superficiale

Qual è la differenza tra profonda e superficiale copia. Che tipo di copia fa un costruttore di copie?

+2

Duplicato di http://stackoverflow.com/questions/184710/quello-è-differenza-dato-a-deposito-deposito-e-sono-copia- –

+0

1a domanda è un duplicato, ma posso trovo il 2 °, anche se potrebbe essere perché non è indicato chiaramente. @ Ankur: nella tua seconda domanda, stai chiedendo del costruttore di copie predefinito? – outis

+1

I termini deep vs shallow copy non sono in genere utilizzati in C++, poiché non sono particolarmente adatti alla lingua. In Java e in molti altri linguaggi, la distinzione è più utile a causa della loro semantica basata sui riferimenti, rendendo la copia superficiale inevitabile nella maggior parte dei casi. In C++, dove gli oggetti vengono copiati in base al valore, le copie poco profonde sono molto rare, ma il costruttore di copie predefinito non implementerà neanche una copia profonda. I termini non hanno senso in C++ – jalf

risposta

10

L'esempio per eccellenza di questo è un array di puntatori a strutture o oggetti (che sono mutabili).

A copia superficiale copia la matrice e mantiene i riferimenti agli oggetti originali.

A la copia profonda copierà (clonerà) anche gli oggetti in modo che non abbiano alcuna relazione con l'originale. Implicito in questo è che gli oggetti stessi sono copiati in profondità. È qui che diventa difficile perché non esiste un modo reale per sapere se qualcosa è stato copiato o no.

Il costruttore di copie viene utilizzato per inizializzare il nuovo oggetto con l'oggetto precedentemente creato della stessa classe. Di default il compilatore ha scritto una copia superficiale. La copia superficiale funziona bene quando l'allocazione dinamica della memoria non è coinvolta perché quando è coinvolta l'allocazione dinamica della memoria allora entrambi gli oggetti puntano verso la stessa posizione di memoria in un heap, quindi per rimuovere questo problema abbiamo scritto una copia profonda in modo che entrambi gli oggetti abbiano la loro copia degli attributi in un ricordo.

Per leggere i dettagli con esempi e spiegazioni completi è possibile vedere l'articolo Constructors and destructors.

Il costruttore di copie predefinito è poco profondo. È possibile creare i propri costruttori di copia in profondità o in profondità, a seconda dei casi. Vedi C++ Notes: OOP: Copy Constructors.

+3

Dovrebbe essere * un array di ** puntatori a ** oggetti mutabili * –

+0

Un buon esempio è Boost :: GIL dove le viste sono copie superficiali di oggetti immagine (contenitori di pixel). Le copie locali/temporanee dei pixel vengono create quando si accede tramite l'oggetto vista. – jiggunjer

46

copia superficiale:

Alcuni membri della copia può fare riferimento agli stessi oggetti dell'originale:

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

Qui, la pi utente dell'originale e copiato X oggetto saranno entrambi scegliere lo stesso int.


copia completa:

Tutti i membri degli originali vengono clonati (in modo ricorsivo, se necessario). Non ci sono oggetti condivisi:

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

Qui, il pi membro del X oggetto originale e copiato punterà a diversi int oggetti, ma entrambi questi hanno lo stesso valore.


Il costruttore di copia di default (che è fornita automaticamente se non si fornisce uno voi stessi) crea copie solo poco profonde.

Correzione: Diversi commenti qui sotto hanno giustamente fatto notare che è sbagliato dire che la copia costruttore di default sempre esegue una copia (o una copia profonda, è per questo). Se il costruttore di copie di un tipo crea una copia poco profonda o copia profonda, o qualcosa tra i due, dipende dalla combinazione del comportamento di copia di ciascun membro; il costruttore di copie di un membro può essere fatto per fare quello che vuole, dopo tutto.

Ecco quale sezione 12,8, comma 8 della norma del 1998, C++ dice circa gli esempi di codice di cui sopra:

Il implicitamente definito copia costruttore per la classe X esegue una copia membro a membro dei suoi oggetti secondari. [...] Ogni sottooggetto viene copiato nel modo appropriato al suo tipo: [...] [I] il sottoboject è di tipo scalare, l'operatore di assegnazione incorporato è utilizzato.

+1

Il paragrafo criptico sembra non essere d'accordo con la tua audace affermazione che il costruttore di copie predefinito faccia solo copie superficiali. – UncleBens

+0

Cosa ti fa pensare così? Lo capisco come segue: i membri di qualche tipo di puntatore sono un subobject scalare, no?E se copi un puntatore usando l'operatore di assegnazione integrato, ciò significa che l'oggetto puntato non sarà clonato, ma sarà semplicemente chiamato da un puntatore aggiuntivo. Quindi finisci con una copia superficiale. – stakx

+1

@stakx Hai ragione, ma penso che questo dimostri che i termini "copia profonda" e "copia superficiale" non sono particolarmente utili - in realtà non li ho mai sentiti usati dai programmatori C++ esperti. –

2

La copia profonda esegue letteralmente una copia profonda. Significa che se la tua classe ha dei campi che sono riferimenti, i loro valori saranno copiati, non i riferimenti stessi. Se, ad esempio, hai due istanze di una classe, A & B con campi di tipo di riferimento ed esegui una copia profonda, la modifica di un valore di quel campo in A non influirà su un valore in B. E viceversa. Le cose sono diverse con la copia superficiale, perché vengono copiati solo i riferimenti, pertanto la modifica di questo campo in un oggetto copiato influirebbe sull'oggetto originale.

Che tipo di copia fa un costruttore di copia?

È in funzione dell'implementazione. Ciò significa che non ci sono regole rigide su questo, è possibile implementarlo come una copia profonda o una copia superficiale, tuttavia per quanto ne so è una pratica comune implementare una copia profonda in un costruttore di copie. Tuttavia, un costruttore di copie predefinito esegue una copia superficiale.

Problemi correlati