在 STL 中使用 void* 作为固定宽度记录

Working with void* as fixed width records in STL

本文关键字:固定宽度 记录 void STL      更新时间:2023-10-16

我有一个连续的缓冲区,有 N 条记录,每条记录 W 字节宽。N 和 W 在编译时是未知的。N*M 是 500mb 的订单。我想在标准的STL argorithms中使用它,例如sort()或nth_element()。我手头确实有一个比较器。有没有已经实施的方法可以做到这一点?

到目前为止,我想到了两种方法:

1)使用一个额外的向量,

用索引0...N填充,对其进行排序(使用自定义比较器)而不是数据,使其类似于排序顺序的数据记录,然后根据该向量移动数据记录。缺点:额外的内存,额外的困难来修复数据记录顺序,这稍微不平凡。

2)创建一些自定义迭代器(知道W),它将返回一些类似于记录的临时"虚拟"类实例,并为该类重载swap(),以便它交换内存块。缺点:有点棘手,有点脆弱(需要遵循一些 STL 内部,例如知道将使用 swap()。

您的第二个选项(编写自定义迭代器)是一种可行的方法,并且效果很好。

您不需要依赖正在使用的swap:您只需要重载在取消引用迭代器时返回的代理对象的赋值运算符。

(请注意,在 C++11 中,"交换"元素的算法和函数需要使用通过 ADL 找到的swap函数。 不过,重载赋值运算符仍然更可取,特别是如果您只是移动字节数组。

我不知道我的头顶上的一般实现,但作为起点,您可以从我的一个库(靠近文件底部)查看stride_iterator。 它包装一个字节数组并覆盖算术运算符,以一次将迭代器移动 N 个字节,其中 N 仅在运行时已知。

我会选择第二种方法,但通过提供自定义复制语义,而不是自定义swap。使迭代器值类型成为保存void*成员的类,并具有复制构造函数和复制该成员指向的记录的赋值运算符。这不依赖于任何实现细节。

我会投票支持选项 2),但您实际上不需要为存根类重载swap()。您只需要:

  • 创建由迭代器返回的"存根"类
  • 实现默认的 ctor,它分配一个宽度为 W 的内存块
  • 实现复制 ctor,它分配宽度为 W 的内存块,并复制内存的输入块
  • 重载赋值运算符,以便将内存块从一个实例复制到另一个实例。

这样,swap()将自动为您的班级工作。