【问题标题】:Fast default ordering for POD class in C++C++ 中 POD 类的快速默认排序
【发布时间】:2014-08-29 09:52:35
【问题描述】:

假设我在 C++ 中有一些 POD struct Foo,我想将其放入像 set<Foo> 这样的有序容器中。我不关心使用哪种排序,只关心它是一致的和快速的。最好的方法是什么?

更具体地说,假设我在一台带有sizeof(long)==8 的 64 位机器上。说类是:

 struct Foo{
  long key; //8 bytes : 8 total
  int fum;  // 4 bytes : 12 total
  short n;  // 2 bytes : 14 total
  short n[3];  //6 bytes : 20 total
  char bar[5];  // 5 bytes : 25 total
  char name[23]; //22 bytes : 47 total
  char padding[1]; // 1 byte : 48 total 
 }

padding 字段只是为了确保大小是 8 的倍数。

注意sizeof(Foo) 是 48,所以它的内容可以用 6 个unsigned longs 表示,这显然是进行比较的最佳方式,而不是遍历每个字段。

编译器可以自动为我执行此操作吗?或者我是否必须使用字段unsigned long data[8] 定义union,或者在Foo 的operator< 方法中将Foo * 转换为unsigned long *?

请注意,如果没有填充字段,则必须生成 5 个 unsigned long 比较,然后是 long、short 和 char 比较。这整件事有点乱。

这个问题必须一直出现,所以我猜有一些最好/最好的方法来处理它。

【问题讨论】:

  • 你固定在std::set上吗?也许std::unordered_set 结合散列函数可能是一个不错的选择(如果您只使用它进行快速查找,并且不需要顺序)。

标签: c++ stl containers comparison-operators


【解决方案1】:

如果您想使用 struct 实际值进行比较,最好定义一个 operator<,它具有更多逻辑并在字段之间提供某种逻辑排序。

如果您只希望对象可排序以便快速访问,则只需按住指针即可。这些只是数字,并且是可排序的。

如果您想使用实际的结构数据,但不关心成员之间的任何排序,您可以使用 memcmp 和 sizeof(Foo)。

【讨论】:

  • 我想我会使用 sizeof(Foo) - sizeof(padding) ,因为不能真正保证两个其他相同成员的填充是相同的
  • 正如我在问题的第 2 句中所说,我只关心提到的订单属性。指针的想法在这种情况下是不适用的。显然,如果我有指向规范对象的指针,我根本不需要比较器。容器的一个原因是获得这样的指针。 memcmp 具有正确的签名,但(尚未计时)似乎太慢了。它处理更复杂的语义,是一个运行时函数。
  • 我怀疑你会比 memcmp 快很多。它根本不处理任何语义。
  • 好的,我会在某个时候计时。感谢您的指点(可以这么说)。
  • 我关心的是这个 memcmp 代码 code.google.com/p/pic30/source/browse/branches/v3_24/gcc-4.0.3/… 。例如,它只使用逐字节比较而不是使用无符号长整数。我将 libc++ 与 clang++ 一起使用,根据我的经验,它并不完全是效率的典范。但就像我说的,我会测试它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-19
  • 2011-03-29
  • 2017-02-18
  • 2010-11-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多