我有一个指向结构的指针,我需要实现一个复制结构的所有内存内容的方法。一般来说,我需要执行结构的深层复制。
这是结构:
typedef struct {
Size2f spriteSize;
Vertex2f *vertices;
GLubyte *vertex_indices;
} tSprite;
这是我实现的方法应该复制结构:
tSprite* copySprite(const tSprite *copyFromMe)
{
tSprite *pSpriteToReturn = (tSprite*)malloc( sizeof(*copyFromMe) );
memcpy(pSpriteToReturn, copyFromMe, sizeof(*copyFromMe) );
return pSpriteToReturn;
}
问题是我不确定数组“vertices”和“vertex_indices”是否会被正确复制。什么会以这种方式被复制?数组的地址或数组本身?
我应该在复制结构后复制数组吗?或者仅仅复制结构就足够了吗?
这样的事情:
...
pSpriteToReturn->vertices = (Vector2f*)malloc( sizeof(arraysize) );
memcpy(pSpriteToReturn->vertices, copyFromMe->vertices, sizeof(arraysize) );
...
提前谢谢。
答案 0 :(得分:8)
根据经验,不要在普通代码中使用C ++中的memcpy
(可能在非常低级别的代码中出现,例如在分配器中) 1)。相反,创建一个合适的复制构造函数并重载operator =
(赋值运算符)以匹配它(和一个析构函数 - 三个规则:“如果你实现了复制构造函数{{1和析构函数,必须实现所有这三个。)
如果您没有实现自己版本的复制构造函数和赋值运算符,C ++将为您创建默认版本。这些版本将实现一个浅拷贝(很像operator =
会做的),即在你的情况下,数组内容将不被复制 - 只有指针。
1)顺便提一下,memcpy
和malloc
也是如此。不要使用它们,而是使用free
/ new
和new[]
/ delete
。
答案 1 :(得分:3)
这部分取决于您的要求。如果不复制数组,则两个结构都将指向同一个数组,这可能是也可能不是问题。
答案 2 :(得分:3)
您的方案将复制阵列的地址。返回的“copy”tSprite
将指向与传入的相同数据(在内存中)。
如果你想要一个真正的深拷贝,你需要手动复制数组(及其元素的任何成员)。
答案 3 :(得分:2)
如果你正在写C ++,那么请记住C ++有new
和delete
是有原因的。至于问题本身,它取决于你是否想要复制指针或结构本身。如果是后者,你也需要复制它们!
答案 4 :(得分:1)
即使您在普通的C中工作,这也不是正确的复制方法。
在另一个答案中指出,最终会有两个(或更多)结构实例指向同一个Vertext2
和GLubyte
实例,这是不推荐的。
这会导致诸如谁将释放内存分配给Vertext2
GLubyte
等问题
Should I copy the arrays after copying the structure? Or is it enough just to copy the structure?
是的,这是正确的方法
答案 5 :(得分:1)
指针本身将被复制,但这意味着两个精灵中的“from”和“to”都是相同的。您还需要手动分配和复制指针指向的内容,但这意味着您还需要知道指针引用的数组有多大。
请注意,除了memcpy之外,您还可以执行'* pSpriteToReturn = * copyFromMe;'这将复制所有成员,但如果您要创建新数组,那么您想要实际复制的tSprites中唯一的部分就是大小。
另一个注意事项是,如果你的精灵总是有固定数量的顶点和顶点索引,你可以在精灵中使这些数组而不是指针。如果你这样做,那么它们将使用memcpy方法和我在上一段中提到的赋值正确复制。
答案 6 :(得分:1)
在C ++中新建并删除堆上的分配。
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[]