C++: структура будет скопирована правильно?

У меня есть указатель на структуру, и я должен реализовать метод, который скопирует все содержание памяти структуры. Вообще говоря, я должен выполнить глубокую копию структуры.

Вот структура:

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

Проблема состоит в том, что я не уверен, что массивы "вершины" и "vertex_indices" будут скопированными правильно. Что будет скопированным таким образом? Адрес массива или самого массива?

Я должен скопировать массивы после копирования структуры? Или это достаточно только для копирования структуры?

Что-то вроде этого:

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

Заранее спасибо.

7
задан Ilya Suzdalnitski 21 January 2010 в 19:55
поделиться

7 ответов

Последнее место, где я должен был что-то разблокировать, было при написании кода, который получил некоторые данные из базы данных (я не использовал LINQ в SQL , просто простой старый ADO.NET ):

int myIntValue = (int)reader["MyIntValue"];

В основном, если вы работаете со старыми API до дженериков, вы столкнетесь с боксом. Кроме этого, это не так часто встречается.

-121--544360-

Вы не можете сделать это в одном запросе в Джанго. Вы можете получить клиенту только дату их последней покупки, например:

from django.db.models import Max
customers = Customer.objects.annotate(Max('purchase__date'))

, но вы не получаете автоматический доступ к фактической покупке в этом пути.

-121--3713338-

Как правило, никогда не используйте memcpy в C++ в обычном коде (он может обрезаться в очень низкоуровневом коде, например, в распределителях) 1) . Вместо этого создайте подходящий конструктор копирования и перегрузите оператор = (оператор назначения), чтобы соответствовать ему ( и деструктор - правило из трех: "если вы реализуете любой из конструктора копирования, оператор = и деструктор, вы должны реализовать все три).

Если вы не реализуете собственные версии конструктора копирования оператором назначения, C++ создаст для вас версии по умолчанию. В этих версиях будет реализована неглубокая копия (так же, как и memcpy ), т.е. в вашем случае содержимое массива не будет скопировано - только указатели.


1) Кстати, то же самое относится к malloc и free . Не используйте их, вместо этого используйте new / new [] и delete / delete [] .

8
ответ дан 6 December 2019 в 10:00
поделиться

Это частично зависит от ваших требований. Если вы не копируете массивы, обе структуры будут указывать на тот же массив, который может быть или не может быть проблемой.

3
ответ дан 6 December 2019 в 10:00
поделиться

Если это C ++, в котором вы пишете, то помните, что C ++ новый и удалить по причине. Что касается самого вопроса, это зависит, хотите ли вы копировать указатели или сами структуры. Если последний, вам нужно скопировать их тоже!

2
ответ дан 6 December 2019 в 10:00
поделиться

Это не правильный способ скопировать, даже если вы работаете в простых C.

a, указанные в другом ответе, вы окажетесь с двумя (или более) экземплярами структуры. Указывая на тот же Vertext2 и Plubyte экземпляр , который не рекомендуется.

Это приведет к тому, как проблемы, такие как кто освободит память, выделенный на Vertext2 Glubyte

Должен ли я копировать массивы после копирования структуры? Или это достаточно, чтобы скопировать структуру?

Да, это правильный способ сделать это

1
ответ дан 6 December 2019 в 10:00
поделиться

Сами указатели будут скопированы, но это означает, что как «от», так и «к» будут одинаковыми в двух спрайтах. Вам также потребуется вручную выделить и скопировать вещи, указанные на указателях, но это подразумевает, что вам также нужно знать, насколько большими массивами являются личными указателями.

Обратите внимание, что вместо memcpy там вы также можете сделать * pspriteToreturn = * copyFromme; Это скопируют все члены, хотя, если вы собираетесь создавать новые массивы, единственную часть TSPRITS, которые вы хотите скопировать, это размер.

Другое примечание было бы то, что если ваши спрайты всегда имеют фиксированное количество вершин и индексов верхов, вы можете сделать эти массивы внутри спрайта, а не указателями. Если вы сделали это, то они будут правильно скопированы как с методом MEMCPY, так и назначением, которое я упоминаю в вышеприведенном пункте.

1
ответ дан 6 December 2019 в 10:00
поделиться

в 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
ответ дан 6 December 2019 в 10:00
поделиться

Ваша схема собирается скопировать адреса массивов. Вернулся «Копировать» T4PRITE , укажет указатели на те же данные (в памяти), как пропущенные в одном.

Если вы хотите верную глубокую копию, вам нужно копировать массивы (и любые элементы их элементов) вручную.

3
ответ дан 6 December 2019 в 10:00
поделиться