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 2

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