2010-01-21 12 views
7

Ho un puntatore a una struttura e ho bisogno di implementare un metodo che copierà tutto il contenuto della memoria di una struttura. In generale, ho bisogno di eseguire una copia profonda di una struttura.C++: la struttura verrà copiata correttamente?

Ecco la struttura:

typedef struct { 
    Size2f spriteSize; 

    Vertex2f *vertices; 

    GLubyte *vertex_indices; 
} tSprite; 

Ed ecco il metodo che ho implementato che dovrebbe copiare la struttura:

tSprite* copySprite(const tSprite *copyFromMe) 
{ 

    tSprite *pSpriteToReturn = (tSprite*)malloc(sizeof(*copyFromMe)); 

    memcpy(pSpriteToReturn, copyFromMe, sizeof(*copyFromMe)); 

    return pSpriteToReturn; 
} 

Il problema è che io non sono sicuro che gli array "vertici" e "vertex_indices" verranno copiati correttamente. Cosa verrà copiato in questo modo? Indirizzo dell'array o dell'array stesso?

Devo copiare gli array dopo aver copiato la struttura? O è sufficiente solo per copiare la struttura?

Qualcosa di simile a questo:

... 
pSpriteToReturn->vertices = (Vector2f*)malloc(sizeof(arraysize)); 
memcpy(pSpriteToReturn->vertices, copyFromMe->vertices, sizeof(arraysize)); 
... 

Grazie in anticipo.

+2

Dipende. Una copia dovrebbe essere una copia profonda, con vertici indipendenti * e * vertex_indices, o entrambe le copie dovrebbero condividere una singola copia dei dati? Come attualmente scritto, copySprite copia solo in modo superficiale i puntatori e condividono dati comuni. – Joe

+3

Non sei sicuro del motivo per cui hai codificato questo C++ quando tutto il tuo codice è dritto C. –

+0

Se il problema è C. Quindi esegue correttamente una copia superficiale. Se il problema è C++, apriamo un'intera scatola di worm che non può essere risolta perché non ci sono abbastanza informazioni. –

risposta

8

Come regola generale, non mai utilizzare memcpy in C++ nel codice normale (si potrebbe affiorano in molto codice di basso livello, ad esempio in allocatori) 1). Invece, creare un adeguato costruttore di copia e di sovraccarico operator = (l'operatore di assegnazione) per abbinarlo (e un distruttore - regola del tre: “se si implementa una di costruttore di copia, operator = e distruttore, si deve implementare tutti e tre) .

Se non si implementano le proprie versioni del costruttore di copie e l'operatore di assegnazione, C++ creerà automaticamente le versioni predefinite. Queste versioni implementeranno una copia superficiale (molto simile a quello che farebbe lo memcpy), cioè nel tuo caso il contenuto dell'array sarebbe non da copiare - solo i puntatori.


1) inciso, lo stesso vale per malloc e free. Non utilizzarli, invece utilizzare new/new[] e delete/delete[].

+0

Grazie, ma per quanto riguarda la copia degli array in stile c? Come posso copiarli senza usare memcpy? –

+1

usa new [] per allocare, std :: copy to copy, delete [] per eliminare – Anycorn

+0

@Ilya: puoi usare 'std :: copy'. Inoltre, hai davvero bisogno di usare gli array in stile C o comunque 'std :: vector' non è una soluzione migliore? –

3

Questo parzialmente dipende dalle vostre esigenze. Se non si copiano gli array, entrambe le strutture punteranno allo stesso array, il che potrebbe essere o meno un problema.

3

Lo schema sta per copiare gli indirizzi degli array. La "copia" tSprite restituita avrà i puntatori agli stessi dati (in memoria) come passati in uno.

Se si desidera una vera copia in profondità, è necessario copiare manualmente gli array (e qualsiasi membro dei relativi elementi).

2

Se è il C++ in cui stai scrivendo, ricorda che C++ ha new e delete per un motivo. Per quanto riguarda la domanda in sé dipende se vuoi copiare i puntatori o le strutture stesse. Se quest'ultimo, è necessario copiare anche loro!

+0

Cosa ti farebbe pensare che l'autore stia scrivendo in C++? –

+0

@dash: tag C++ nella domanda? ;> –

1

Questo non è il modo giusto per copiare anche se si sta lavorando in pianura C.

Un sottolineato nell'altra risposta, si finirà con due (o più) istanze di struct che puntano alla stessa istanza Vertext2 e GLubyte, che non è consigliabile.

Ciò porterebbe a questioni come chi libererà la memoria allocare per Vertext2GLubyte

Should I copy the arrays after copying the structure? Or is it enough just to copy the structure?

Sì questo è il modo giusto per farlo

1

I puntatori stessi saranno copiati, ma che significa che sia "da" che "a" sarà lo stesso nei due sprite. Dovrai inoltre allocare e copiare manualmente le cose indicate dai puntatori, ma ciò implica che devi anche sapere quanto sono grandi gli array a cui fanno riferimento i puntatori.

Nota che invece di memcpy lassù, puoi anche fare '* pSpriteToReturn = * copyFromMe;' Questo copierà tutti i membri, anche se se stai per creare nuovi array, l'unica parte degli tSprites che vuoi copiare effettivamente è la dimensione.

Un'altra nota potrebbe essere che se gli sprite hanno sempre un numero fisso di vertici e vert indici, è possibile creare tali matrici all'interno dello sprite anziché puntatori. Se lo facessi, verrebbero copiati correttamente sia con il metodo memcpy sia con l'assegnazione che menziono nel paragrafo precedente.

1

in C++ nuovo e cancella allocare su heap.

Sprite *ptr =...; 
Sprite *s = new Stripe(*ptr); // copy constructor, shallow copy off pointers 
s->member = new Member(*ptr->member); // copy construct sprite member 

s->array = new int[4]; //allocate array 
std::copy(ptr-> array, ptr->array + 4, s->array); //copy array 
delete[] s->array; //delete array, must use delete[] 
Problemi correlati