在某些C ++项目中,我正在处理代表各种性质图形的对象。它们都实现了一个通用的抽象接口,我将这个接口简化为一个函数:
class graph {
public:
...
// Create an iterator over the successors of v
virtual succ_iterator* succ(const vertex* v) const = 0;
...
};
succ_iterator
类也是一个抽象类,可以迭代v
的后继顶点:
class succ_iterator {
public:
virtual void first() = 0; // reset the iterator
virtual void next() = 0; // move to next successor
virtual bool done() const = 0; // no more successor left?
virtual const vertex* dest() const = 0; // destination vertex
};
因此,图v
中g
的所有后继者的循环如下所示:
succ_iterator* i = g->succ(v);
for (i->first(); !i->done(); i->next()) {
// use i->dest()
}
delete i;
我经常使用这样的循环来实现图算法。 分析代码表明它花费了大量时间为这些微小的迭代器实例分配内存,所以我想听听有关改进这一点的想法。
不幸的是,我的图形可能有非常不同的实现,因此每个图形可能有自己的succ_iterator
接口实现。实质上,graph
层次结构中的每个类在succ_iterator
层次结构中都有对应的类。例如,可以使用std::vector
实现一个图来明确地存储邻接列表(在这种情况下,succ_iterator
是std::vector::const_iterator
上方的简单包装器),而另一个图可能是在...上计算的。 fly(在这种情况下,它的succ_iterator
实例实际上将计算后续进程中的继承者)。我不知道编译时图形的性质,因此这排除了基于template
的实现àla STL。
我考虑过允许每个图表处理succ_iterator
池。这似乎需要一个额外的graph::succ_release(succ_iterator*)
方法来将迭代器返回到池而不是删除它。我见过的大多数池都是在内存级别完成的:即,当你释放一个对象时,它的析构函数被调用,但是被占用的内存被保留,以便下一个对象将被创建(使用就地构造函数)块。这似乎仍然浪费时间,因为就地构造函数必须设置一个与前一个对象相同的虚拟表指针。我认为在这样的池中,我应该用delete
方法替换new
+ recycle()
,该方法与构造函数具有相同的原型。由于代码库非常大,这需要更改界面,我希望在实现之前了解其他设计思路或可能的改进。
编辑:我不使用线程。
答案 0 :(得分:0)
你可以在每个图形实例中缓存succ_iterators并在需要时查找并重用它们吗?
//static or member:
std::map<graph*,succ_iterator*> graph_iterator_cache;
但我不知道你是否有安全问题。