2010-01-21 10 views
7

Tengo un puntero a una estructura y necesito implementar un método que copie todos los contenidos de la memoria de una estructura. En términos generales, necesito realizar una copia profunda de una estructura.C++: ¿Se copiará la estructura correctamente?

Aquí está la estructura:

typedef struct { 
    Size2f spriteSize; 

    Vertex2f *vertices; 

    GLubyte *vertex_indices; 
} tSprite; 

Y aquí es el método que yo he implementado que debe copiar la estructura:

tSprite* copySprite(const tSprite *copyFromMe) 
{ 

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

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

    return pSpriteToReturn; 
} 

El problema es que no estoy seguro de que las matrices "vértices" y "vertex_indices" se van a copiar correctamente. ¿Qué se va a copiar de esta manera? Dirección de la matriz o la matriz en sí?

¿Debo copiar las matrices después de copiar la estructura? ¿O es suficiente solo copiar la estructura?

Algo como esto:

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

Gracias de antemano.

+2

Depende. ¿Debe una copia ser una copia profunda, con vértices independientes * y * vertex_indices, o ambas copias deben compartir una sola copia de los datos? Tal como está escrito actualmente, copySprite solo copiará los punteros y compartirán datos comunes. – Joe

+3

No estoy seguro de por qué ha etiquetado este C++ cuando todo su código es directo C. –

+0

Si el problema es C. Entonces hace una copia poco profunda. Si el problema es C++, abrimos una lata de gusanos que no se puede responder porque no hay suficiente información. –

Respuesta

8

Como regla general, no utilizar nunca memcpy en C++ en código normal (que fuerzas surgen en el código de nivel muy bajo, por ejemplo, en los asignadores) 1). En su lugar, crear un constructor de copia adecuada y la sobrecarga operator = (el operador de asignación) para que coincida con ella (y un destructor - regla de tres: “si la aplicación de cualquiera de constructor de copia, operator = y el destructor, que debe poner en práctica los tres) .

Si no implementa sus propias versiones del constructor de copia y el operador de asignación, C++ creará versiones predeterminadas para usted. Estas versiones implementarán una copia superficial (muy similar a lo que haría memcpy), es decir, en su caso los contenidos de la matriz serían no se copiarán, solo los punteros.


1) Incidentalmente, lo mismo vale para malloc y free. No los use, en su lugar use new/new[] y delete/delete[].

+0

Gracias, pero ¿qué pasa con la copia de arreglos c-styled? ¿Cómo puedo copiarlos sin usar memcpy? –

+1

use nuevo [] para asignar, std :: copiar para copiar, eliminar [] para eliminar – Anycorn

+0

@Ilya: puede usar 'std :: copy'. Por otra parte, ¿de verdad necesita usar matrices de estilo C de todos modos o podría 'std :: vector' no ser una mejor solución? –

3

Esto depende parcialmente de sus requisitos. Si no copia las matrices, ambas estructuras apuntarán a la misma matriz, lo que puede o no ser un problema.

3

Su esquema va a copiar las direcciones de las matrices. La "copia" tSprite devuelta va a tener punteros a los mismos datos (en memoria) que los pasados ​​en uno.

Si desea una copia profunda verdadera, deberá copiar las matrices (y los elementos de sus elementos) manualmente.

2

Si está escribiendo en C++, entonces recuerde que C++ tiene new y delete por algún motivo. En cuanto a la pregunta en sí misma, depende de si desea copiar punteros o las propias estructuras. Si es este último, ¡también debe copiarlos!

+0

¿Qué le haría pensar que el autor está escribiendo en C++? –

+0

@dash: etiqueta C++ en la pregunta? ;> –

1

Esta no es una forma correcta de copiar, incluso si está trabajando en la C.

A señalado en la otra respuesta, terminará con dos (o más) instancias struct apuntando a la misma instancia Vertext2 y GLubyte, que no es recomendable.

Esto llevaría a cuestiones como quién va a liberar la memoria asignar a Vertext2GLubyte

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

Si esta es la forma correcta de hacerlo

1

Los punteros mismos serán copiados, pero eso significa que tanto "de" como "a" serán los mismos en los dos sprites. También necesitará asignar y copiar manualmente las cosas apuntadas por los punteros, pero eso implica que también necesita saber qué tan grandes son las matrices a las que hacen referencia los punteros.

Tenga en cuenta que en lugar de memcpy allí, también puede hacer '* pSpriteToReturn = * copyFromMe;' Esto copiará todos los miembros, aunque si va a crear nuevas matrices, la única parte de tSprites que desea copiar realmente es el tamaño.

Otra nota sería que si tus sprites siempre tienen un número fijo de vértices y de índices vert, puedes hacer esos arreglos dentro del sprite en lugar de los punteros. Si hicieras esto, se copiarían correctamente tanto con el método memcpy como con la tarea que mencioné en el párrafo anterior.

1

en C++ nuevo y eliminar asignar en el montón.

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[] 
Cuestiones relacionadas