开发者

memcpy of a part of a struct

I have a struct/class which is partiall 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;
};

I copy objects of class S a lot. I would like to copy it with memcpy, but S::more prevents it. I would like to avoid call to 4 memcpy's and make it all with one for an extra bit of performance. Should I do someting like this?

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

I can't pack them in separate struct since it would clobb开发者_如何学运维er all the code that uses pod1 - pod4.

What is the best solution?


The best solution is to rely on C++ automatic copy constructor and copy operator. The compiler has then a chance to understand your code and optimize it well. Try to avoid memcpy in C++ code.

If you need to copy only part of the structure, create a method for it:

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


As @Erik said, the code you have won't work because of padding.

However, since you are not using any access declarations, the compiler is required to store the fields in the same order as in the source code, so you can do this:

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

And let the compiler/linker optimize it for you: It will do a way better job than you. And you eliminate the risk to bring nasty bugs into the game (such as alignment, packing,...).


This is not safe, there's no guarantee that the structs are packed, there can be empty space in between them for alignment purposes.

Using assignment and/or copy construction is safe, and until proven otherwise with a profiler it's as fast as memcpy ;).

EDIT: If you really want to use memcpy, here's a possible but horrible solution:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜