我有一个2d矩形网格,我需要将不同的函数应用于此网格中的节点子集。该子集由矩形边界给出,例如行和列分隔符。由于我不想一遍又一遍地用2 for循环编写迭代代码,我正在考虑两种方法来解决这个问题:
首先创建一个自定义迭代器提供程序,该提供程序使用矩形限制进行初始化,然后在迭代时保留它们。虽然这是可行的,但是使这个迭代器符合要求似乎还有一些工作要做。与标准的aglithithms。
第二种方法是将函数指针传递给遍历for循环的函数,并在内循环中执行它。这也是可行的,但由于我必须传递成员函数,因此可能会创建非常难看的语法。
哪种方式通常更可取?这个用例有没有干净的例子,让我不再重新发明轮子?
注意:由于代码经常执行,因此操作非常重要,
答案 0 :(得分:1)
为什么不将2d子集数组复制到临时数组,然后将指针传递给数组的开头到不同的函数?
如果将相同的子集多次传递给不同的函数,它应该可以改善缓存未命中率,从而缩短子集迭代所花费的时间。
答案 1 :(得分:1)
从设计的角度来看,我会说迭代器方法更好,因为它在循环体上的复杂性较低(并且可能会比迭代中的复杂性更复杂)。
但我希望通过仿函数方法获得更好的性能。特别是如果您将使用STL样式(带有预期operator()的模板参数)。
答案 2 :(得分:1)
这里值得的是我最终实现的算法。代码不完整,但可能对其他人有用:
//forward declarations
template <typename T> class Grid;
template <typename T> class rectIterator;
//friend forward declarations
template<class T>
bool operator!=(rectIterator<T> const& left, rectIterator<T> const& right);
template<class T>
class rectIterator: public std::iterator<std::forward_iterator_tag, GridTile<T> >{
public:
typedef GridTile<T> const& const_reference;
typedef GridTile<T>& reference;
typedef GridTile<T> const* const_pointer;
typedef GridTile<T>* pointer;
private:
Grid<T>* mpGrid;
int mRow;
int mCol;
int mMinRow;
int mMinCol;
int mMaxRow;
int mMaxCol;
public:
rectIterator(Grid<T>& grid,Rectangle const& rect):
mpGrid(&grid){
mpGrid->getRowCol(mpGrid->getTileId(rect.bottomLeft()),mMinRow,mMinCol);
mpGrid->getRowCol(mpGrid->getTileId(rect.topRight()),mMaxRow,mMaxCol);
mRow = mMinRow;
mCol = mMinCol;
}
rectIterator():
mpGrid(0){
mMinRow= -1;
mMinCol=-1;
mMaxRow =-1;
mMaxCol =-1;
mCol = 0;
mRow = 0;
}
rectIterator<T>& operator++(){
if(mCol<=mMaxCol){
++mCol;
}else if(mRow<=mMaxRow){
++mRow;
mCol = mMinCol;
}else{
mCol = mpGrid->getCols();
mRow = mpGrid->getRows();
mpGrid=0;
}
return *this;
}
reference operator*() const throw(std::out_of_range, std::runtime_error){
return mpGrid->at(mRow,mCol);
}
pointer operator->() const throw(std::out_of_range, std::runtime_error){
return &(mpGrid->at(mRow,mCol));
}
int row()const{
return mRow;
}
int col()const{
return mCol;
}
friend bool operator!=<>(rectIterator<T> const& left, rectIterator<T> const& right);
};
template<class T>
bool operator!= (rectIterator<T> const& left, rectIterator<T> const& right){
return (left.mpGrid != right.mpGrid);
//DIRTY this is no full compare but fast and sufficient at the moment
}