memcpy части структуры
У меня есть структура / класс, который является частично простыми старыми данными (POD).
struct S {
// plain-old-data structs with only arrays and members of basic types (no pointers);
Pod1 pod1;
Pod2 pod2;
Pod3 pod3;
Pod4 pod4;
vector<int> more;
};
Я много копирую объекты класса S. Я хотел бы скопировать его с помощью memcpy, но S::more мешает этому. Я бы хотел, чтобы избежать вызова функции memcpy 4 и сделать все это с одним за дополнительную производительность. Должен ли я сделать что-то подобное?
memcpy(s1, s2, sizeof(Pod1) + sizeof(Pod2) + sizeof(Pod3) + sizeof(Pod4);
Я не могу упаковать их в отдельную структуру, так как это разрушит весь код, который использует pod1 - pod4.
Какое решение является наилучшим?
4 ответа:
Лучшее решение-полагаться на C++ автоматический конструктор копирования и оператор копирования. После этого компилятор имеет возможность понять ваш код и хорошо его оптимизировать. Старайтесь избегать memcpy в коде C++.
Если вам нужно скопировать только часть структуры, создайте для нее Метод:
struct S { // plain-old-data structs with only arrays and members of basic types (no pointers); Pod1 pod1; Pod2 pod2; Pod3 pod3; Pod4 pod4; vector<int> more; }; void copyPartOfS(S& to, const S& from) { s.pod1 = from.pod1; s.pod2 = from.pod2; s.pod3 = from.pod3; s.pod4 = from.pod4; } ... S one, two; one = two; // Full copy copyPartOfS(one, two); // Partial copy
Как @Erik сказал, Код у вас не будет работать из-за заполнения.
Однако, поскольку вы не используете никаких объявлений доступа, компилятор должен хранить поля в том же порядке, что и в исходном коде, поэтому вы можете сделать следующее:
struct S { // plain-old-data structs with only arrays and members of basic types (no pointers); Pod1 pod1; Pod2 pod2; Pod3 pod3; Pod4 pod4; vector<int> more; }; memcpy(&s1.pod1, &s2.pod1, (char*)(1 + &s1.pod4) - (char*)(&s1.pod1));
void CopyPods(Struct S& s1, Struct S& s2) { s2.pod1=s1.pod1; s2.pod2=s1.pod2; s2.pod3=s1.pod3; s2.pod4=s1.pod4; }
И пусть компилятор / компоновщик оптимизирует его для вас: он будет делать намного лучшую работу, чем вы. И вы исключаете риск привнести в игру неприятные баги (такие как выравнивание, упаковка,...).
Это небезопасно, нет никакой гарантии, что конструкции упакованы, между ними может быть пустое пространство для выравнивания.
Использование конструкции присваивания и / или копирования безопасно, и пока не доказано обратное с помощью профилировщика, это так же быстро, как memcpy ;).
EDIT: если вы действительно хотите использовать memcpy, вот возможное, но ужасное решение:
struct S1 { Pod1 P1; Pod2 P2; }; struct S : S1 { vector<int> more; }; void copy(S & Dest, S const & Src) { memcpy(&Dest, &Src, sizeof(S1)); Dest.more = Src.more; }