memcpy части структуры - PullRequest
2 голосов
/ 15 марта 2011

У меня есть структура / класс, в частности Plain Old Data (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 предотвращает это.Я хотел бы избежать вызова 4 memcpy и сделать все это с одним для дополнительной производительности.Должен ли я сделать что-то вроде этого?

memcpy(s1, s2, sizeof(Pod1) + sizeof(Pod2) + sizeof(Pod3) + sizeof(Pod4);

Я не могу упаковать их в отдельную структуру, так как это приведет к засорению всего кода, который использует pod1 - pod4.

Какое лучшее решение?

Ответы [ 4 ]

10 голосов
/ 15 марта 2011

Лучшее решение - использовать конструктор автоматического копирования 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
2 голосов
/ 15 марта 2011

Как сказал @ Эрик , ваш код не будет работать из-за заполнения.

Однако, поскольку вы не используете какие-либо объявления доступа, компилятор должен хранить поля в том же порядке, что и в исходном коде, поэтому вы можете сделать это:

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));
1 голос
/ 15 марта 2011
void CopyPods(Struct S& s1, Struct S& s2)
{
  s2.pod1=s1.pod1;
  s2.pod2=s1.pod2;
  s2.pod3=s1.pod3;
  s2.pod4=s1.pod4;
}

И пусть компилятор / компоновщик оптимизирует его для вас: он будет работать лучше, чем вы.И вы исключаете риск появления неприятных ошибок в игре (таких как выравнивание, упаковка, ...).

1 голос
/ 15 марта 2011

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

Использование назначения и / или копирования безопасно, и пока не доказано обратное с профилировщиком, это так же быстро, как memcpy;).

РЕДАКТИРОВАТЬ: Если вы действительно хотите использовать 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;
}
...