结构体一部分的 memcpy

发布于 2024-10-22 05:26:50 字数 512 浏览 4 评论 0原文

我有一个结构/类,它是部分纯旧数据(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 的代码。

最好的解决方案是什么?

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 clobber all the code that uses pod1 - pod4.

What is the best solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

好倦 2024-10-29 05:26:50

最好的解决方案是依赖C++自动复制构造函数和复制运算符。然后编译器就有机会理解您的代码并对其进行很好的优化。尽量避免在 C++ 代码中使用 memcpy。

如果您只需要复制结构的一部分,请为其创建一个方法:

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

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
痴者 2024-10-29 05:26:50

正如@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));

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));
檐上三寸雪 2024-10-29 05:26:50
void CopyPods(Struct S& s1, Struct S& s2)
{
  s2.pod1=s1.pod1;
  s2.pod2=s1.pod2;
  s2.pod3=s1.pod3;
  s2.pod4=s1.pod4;
}

让编译器/链接器为您优化它:它会比您做得更好。并且您消除了将讨厌的错误带入游戏的风险(例如对齐、打包等)。

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,...).

樱娆 2024-10-29 05:26:50

这是不安全的,不能保证结构被打包,它们之间可以有空白空间以用于对齐目的。

使用赋值和/或复制构造是安全的,并且除非使用探查器证明否则它与 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;
}

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文