3

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

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

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

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

4

3 回答 3

4

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

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

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

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

于 2012-08-07T16:23:43.250 回答
2

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

于 2012-08-07T16:23:27.990 回答
1

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

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

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

于 2012-08-07T16:24:17.820 回答