c++:结构会被正确复制吗?

时间:2022-05-01 21:40:24

I have a pointer to a structure and I need to implement a method that will copy all of the memory contents of a structure. Generally speaking I need to perform a deep copy of a structure.

我有一个指向结构的指针,我需要实现一个方法来复制结构的所有内存内容。一般来说,我需要对一个结构进行深入的复制。

Here's the structure:

的结构:

typedef struct { 
    Size2f spriteSize;

    Vertex2f *vertices;

    GLubyte *vertex_indices;
} tSprite;

And here's the method I've implemented that should copy the structure:

这是我实现的方法,应该复制结构:

tSprite* copySprite(const tSprite *copyFromMe)
{

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

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

    return pSpriteToReturn;
}

The problem is that I'm not sure that arrays "vertices" and "vertex_indices" are going to be copied properly. What is going to be copied in this way? Address of the array or the array itself?

问题是我不确定数组的“顶点”和“vertex_indices”是否会被正确复制。用这种方式复制什么?数组或数组本身的地址?

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

我应该在复制结构后复制数组吗?还是仅仅复制结构就足够了?

Something like this:

是这样的:

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

Thank you in advance.

提前谢谢你。

7 个解决方案

#1


8  

As a rule of thumb, don’t ever use memcpy in C++ in normal code (it might crop up in very low-level code, e.g. in allocators)1). Instead, create a suitable copy constructor and overload operator = (the assignment operator) to match it (and a destructor – rule of three: “if you implement either of copy constructor, operator = and destructor, you must implement all three).

根据经验,在正常代码中不要在c++中使用memcpy(它可能出现在非常低级的代码中,例如在分配器中)1。相反,创建一个合适的复制构造函数和重载操作符=(赋值操作符)来匹配它(还有一个析构函数- 3的规则:“如果您实现了复制构造函数、操作符=和析构函数中的任何一个,那么您必须实现这三个)。”

If you do not implement your own versions of the copy constructor an the assignment operator, C++ will create default versions for you. These versions will implement a shallow copy (much like what memcpy would do), i.e. in your case the array contents would not be copied – only the pointers.

如果不实现自己版本的复制构造函数和赋值操作符,c++将为您创建默认版本。这些版本将实现一个浅拷贝(很像memcpy所做的),即在您的例子中,数组内容不会被复制——只有指针。


1) Incidentally, the same goes for malloc and free. Don’t use them, instead use new/new[] and delete/delete[].

顺便说一句,malloc和free也是一样。不要使用它们,而是使用new/new[]和delete/delete[]。

#2


3  

This partially depends on your requirements. If you don't copy the arrays, both structures will be pointing to the same array, which may or may not be a problem.

这部分取决于您的需求。如果不复制数组,两个结构都指向同一个数组,这可能是个问题,也可能不是问题。

#3


3  

Your scheme is going to copy the addresses of the arrays. The "copy" tSprite returned is going to have pointers to the same data (in memory) as the passed in one.

你的方案会复制数组的地址。返回的“copy”tSprite将具有指向与传入的相同数据(内存中)的指针。

If you want a true deep-copy, you'll need to copy the arrays (and any members of their elements) manually.

如果想要真正的深度拷贝,需要手动复制数组(以及它们的元素的任何成员)。

#4


2  

If it's C++ you're writing in, then remember that C++ has new and delete for a reason. As for the question itself it depends whether you want to copy pointers or the structures themselves. If the latter, you need to copy them too!

如果你写的是c++,那么记住c++有new和delete是有原因的。至于问题本身,这取决于是要复制指针还是要复制结构本身。如果是后者,您也需要复制它们!

#5


1  

This is not a right way to copy even if you are working in plain C.

这不是一种正确的复制方式,即使您使用的是普通的C语言。

A pointed out in the other answer, you will end up with two(or more) struct instances pointing to same Vertext2 and GLubyte instance, which is not recommended.

另一个答案中指出,您将得到两个(或更多)结构实例指向相同的Vertext2和GLubyte实例,这是不推荐的。

This would lead to issues like who will free the memory allocate to Vertext2 GLubyte

这会导致诸如谁将内存分配释放给Vertext2 GLubyte之类的问题

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

我应该在复制结构后复制数组吗?还是仅仅复制结构就足够了?

Yes this is the right way to do it

是的,这是正确的方法

#6


1  

The pointers themselves will be copied, but that means that both "from" and "to" will be the same in the two sprites. You'll also need to manually allocate and copy the things pointed to by the pointers, but that implies that you also need to know how big the arrays are that are referenced by the pointers.

指针本身将被复制,但这意味着在两个精灵中“from”和“to”都是相同的。您还需要手动分配和复制指针指向的东西,但这意味着您还需要知道指针引用的数组有多大。

Note that instead of memcpy up there, you can also do '*pSpriteToReturn = *copyFromMe;' This'll copy all of the members, although if you're going to make new arrays, the only part of the tSprites that you want to actually copy is the size.

注意,除了上面的memcpy之外,您还可以执行'*pSpriteToReturn = *copyFromMe;'这将复制所有的成员,尽管如果您要创建新的数组,您真正想要复制的tsprite的惟一部分就是大小。

Another note would be that if your sprites always have a fixed number of vertices and vert indices, you can make those arrays inside the sprite rather than pointers. If you did this, then they would be copied correctly with both the memcpy method and the assignment that I mention in the above paragraph.

另一个注意事项是,如果你的精灵总是有固定数量的顶点和索引,你可以在精灵中创建这些数组而不是指针。如果您这样做,那么它们将被正确地复制,使用memcpy方法和我在上面段落中提到的赋值。

#7


1  

in C++ new and delete allocate on heap.

在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[]

#1


8  

As a rule of thumb, don’t ever use memcpy in C++ in normal code (it might crop up in very low-level code, e.g. in allocators)1). Instead, create a suitable copy constructor and overload operator = (the assignment operator) to match it (and a destructor – rule of three: “if you implement either of copy constructor, operator = and destructor, you must implement all three).

根据经验,在正常代码中不要在c++中使用memcpy(它可能出现在非常低级的代码中,例如在分配器中)1。相反,创建一个合适的复制构造函数和重载操作符=(赋值操作符)来匹配它(还有一个析构函数- 3的规则:“如果您实现了复制构造函数、操作符=和析构函数中的任何一个,那么您必须实现这三个)。”

If you do not implement your own versions of the copy constructor an the assignment operator, C++ will create default versions for you. These versions will implement a shallow copy (much like what memcpy would do), i.e. in your case the array contents would not be copied – only the pointers.

如果不实现自己版本的复制构造函数和赋值操作符,c++将为您创建默认版本。这些版本将实现一个浅拷贝(很像memcpy所做的),即在您的例子中,数组内容不会被复制——只有指针。


1) Incidentally, the same goes for malloc and free. Don’t use them, instead use new/new[] and delete/delete[].

顺便说一句,malloc和free也是一样。不要使用它们,而是使用new/new[]和delete/delete[]。

#2


3  

This partially depends on your requirements. If you don't copy the arrays, both structures will be pointing to the same array, which may or may not be a problem.

这部分取决于您的需求。如果不复制数组,两个结构都指向同一个数组,这可能是个问题,也可能不是问题。

#3


3  

Your scheme is going to copy the addresses of the arrays. The "copy" tSprite returned is going to have pointers to the same data (in memory) as the passed in one.

你的方案会复制数组的地址。返回的“copy”tSprite将具有指向与传入的相同数据(内存中)的指针。

If you want a true deep-copy, you'll need to copy the arrays (and any members of their elements) manually.

如果想要真正的深度拷贝,需要手动复制数组(以及它们的元素的任何成员)。

#4


2  

If it's C++ you're writing in, then remember that C++ has new and delete for a reason. As for the question itself it depends whether you want to copy pointers or the structures themselves. If the latter, you need to copy them too!

如果你写的是c++,那么记住c++有new和delete是有原因的。至于问题本身,这取决于是要复制指针还是要复制结构本身。如果是后者,您也需要复制它们!

#5


1  

This is not a right way to copy even if you are working in plain C.

这不是一种正确的复制方式,即使您使用的是普通的C语言。

A pointed out in the other answer, you will end up with two(or more) struct instances pointing to same Vertext2 and GLubyte instance, which is not recommended.

另一个答案中指出,您将得到两个(或更多)结构实例指向相同的Vertext2和GLubyte实例,这是不推荐的。

This would lead to issues like who will free the memory allocate to Vertext2 GLubyte

这会导致诸如谁将内存分配释放给Vertext2 GLubyte之类的问题

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

我应该在复制结构后复制数组吗?还是仅仅复制结构就足够了?

Yes this is the right way to do it

是的,这是正确的方法

#6


1  

The pointers themselves will be copied, but that means that both "from" and "to" will be the same in the two sprites. You'll also need to manually allocate and copy the things pointed to by the pointers, but that implies that you also need to know how big the arrays are that are referenced by the pointers.

指针本身将被复制,但这意味着在两个精灵中“from”和“to”都是相同的。您还需要手动分配和复制指针指向的东西,但这意味着您还需要知道指针引用的数组有多大。

Note that instead of memcpy up there, you can also do '*pSpriteToReturn = *copyFromMe;' This'll copy all of the members, although if you're going to make new arrays, the only part of the tSprites that you want to actually copy is the size.

注意,除了上面的memcpy之外,您还可以执行'*pSpriteToReturn = *copyFromMe;'这将复制所有的成员,尽管如果您要创建新的数组,您真正想要复制的tsprite的惟一部分就是大小。

Another note would be that if your sprites always have a fixed number of vertices and vert indices, you can make those arrays inside the sprite rather than pointers. If you did this, then they would be copied correctly with both the memcpy method and the assignment that I mention in the above paragraph.

另一个注意事项是,如果你的精灵总是有固定数量的顶点和索引,你可以在精灵中创建这些数组而不是指针。如果您这样做,那么它们将被正确地复制,使用memcpy方法和我在上面段落中提到的赋值。

#7


1  

in C++ new and delete allocate on heap.

在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[]