我正在开发一个定义
等接口的SDKclass FooIter
{
// Move to the next foo, return false if there is none.
virtual bool Move() = 0;
// Return a pointer to the current foo.
virtual const void* GetFoo() = 0;
// Get the size of a 'foo', which is a fixed-size POD.
virtual size_t GetFooSize() = 0;
// Get a comparator for foos.
virtual const FooComparator* GetComparator() = 0;
};
class FooComparator
{
virtual int compare(const void* first, const void* second) const = 0;
};
所以基本上,foo是一个opaque类型,我可以将其视为固定长度的二进制缓冲区+和相关的排序函数。
现在,我想在将这些foos传回客户端代码之前对它们进行排序。可能存在很多 foos,因此我将不得不实现外部排序,但我想使用std :: sort来对初始运行进行排序。
我想我会分配一个大小为N * FooIter :: GetFooSize()的缓冲区,使用FooIter填充foos,然后在将其写入磁盘之前使用std :: sort对其进行排序。
我可以从编写迭代器类
开始class FooBufferIter
{
public:
FooBufferIter(const void* fooAddr, int fooSize) : m_fooAddr(fooAddr), m_fooSize(fooSize) {}
FooWrapper operator*() {return FooWrapper(m_fooAddr, m_fooSize);}
FooBufferIter operator++() {return FooBufferIter(m_fooAddr + m_fooSize, m_fooSize);}
// All other needed iterator methods.
private:
const void* m_fooAddr;
int m_fooSize;
};
和foo内存的包装类
class FooWrapper
{
public:
FooWrapper(const void* fooAddr, int fooSize) : m_fooAddr(fooAddr), m_fooSize(fooSize) {}
private:
const void* m_fooAddr;
int m_fooSize;
};
我的理解是std :: sort将使用std :: swap来重新排列序列中的元素。我的问题是我无法看到如何在FooWrapper上专门化std :: swap来有效地执行交换(最重要的是,没有动态分配)。我可以逐字节交换,但这似乎效率低下。
另一种方法是将一个并行的指针序列排序到我的Foo数组中,但我不想这样做,因为在实践中,foos可能会非常小,所以并行序列可以使用和foo序列一样多的内存,我想最大化它一次可以排序的数量。
还有很好的'qsort'可能更适合这种事情,但我不确定如何将FooComparator对象转换为函数指针(可能有多个FooComparator实现)。
还是有更好的方法来解决这个问题吗?我真的不想编写自己的排序实现,虽然它可能不会太很难。
答案 0 :(得分:1)
我将构建一个void *的缓冲区,对它们进行排序,然后生成输出缓冲区。
作为第一步。因为容易。然后编写其他所有内容并寻找性能瓶颈。
下一步,我会看看是否可以完成具有完整类型信息的内部排序。因为最佳。
如果失败了,pod块伪引用迭代器与专门的交换。如果性能测试证明了进一步优化的合理性,那么对于小型med和大型的tomfoolery来说,它可以为大型和数据的小指针排序。
但从KISS开始,先做一些必须先硬的部分。