C++ 为写指针API创建行为良好的迭代器
我必须为API创建一个迭代器,该API只具有旧式的“写出指针”访问器。所讨论的API是OGR的;其中一个类是C++ 为写指针API创建行为良好的迭代器,c++,pointers,stl,iterator,ogr,C++,Pointers,Stl,Iterator,Ogr,我必须为API创建一个迭代器,该API只具有旧式的“写出指针”访问器。所讨论的API是OGR的;其中一个类是ogrlinesting(参考:)。此类存储许多点,可以使用以下getter方法访问这些点: void OGRLineString::getPoint(int pos, OGRPoint *out) 为了使用访问器,用户创建一个新的OGRPoint对象,并将指向该对象的指针传递给方法,该方法将数据写入分配的对象。例如: OGRPoint *p = new OGRPoint(); lin
ogrlinesting
(参考:)。此类存储许多点,可以使用以下getter方法访问这些点:
void OGRLineString::getPoint(int pos, OGRPoint *out)
为了使用访问器,用户创建一个新的OGRPoint
对象,并将指向该对象的指针传递给方法,该方法将数据写入分配的对象。例如:
OGRPoint *p = new OGRPoint();
lineString->getPoint(0, p);
现在,我想实现一个(类似STL的)迭代器。即使我在所有地方都放置了大的警告标志,表明提供的OGRPoint
是不可修改的(即const
),并且如果另一段代码修改正在迭代的ogrlinesting
,我也会遇到OGRPoint const&operator*()const
的内存泄漏问题,因为API要求我传递一个自定义分配的OGRPoint
实例,但迭代器必须分配一个。另外,当迭代器本身被删除时,迭代器返回的OGRPoint
s不应该被删除。此外,ogrlinesting
不存储为getPoint
复制的OGRPoint
的实际实例,而是存储x/y/z坐标的简单结构;所有需要的附加信息(例如,空间参考)都复制到访问者中。因此,一个简单的#define private public
黑客程序是没有用的
是否有任何合理/干净的方法来添加迭代器而不修改原始的ogrlinesting
?例如,有没有一种方法可以像Ruby的“monkey patching”功能那样,将特性添加到原始类中,或者对其进行修改?或者观察容器的生命周期,以便清理迭代器返回的OGRPoint
实例?类this\u is\u my\u迭代器;
class this_is_my_iterator;
class OutputOGRPoint {
explicit OutputOGRPoint(this_is_my_iterator* parent_)
:parent(parent_), p(new OGRPoint())
{}
~OutputOGRPoint();
operator OGRPoint *() {return p;}
OutputOGRPoint(OutputOGRPoint &&)=default;
OutputOGRPoint&operator=(OutputOGRPoint &&)=default;
private:
this_is_my_iterator* parent;
std::unique_ptr<OGRPoint> p;
};
class this_is_my_iterator {
OutputOGRPoint operator*()(return OutputOGRPoint(this);}
private:
friend OutputOGRPoint;
void apply_operator_star_changes(OGRPoint *p);
};
inline OutputOGRPoint::~OutputOGRPoint()
{parent->apply_operator_star_changes(p);}
类输出点{
显式OutputOrpPoint(这个是我的迭代器*父迭代器)
:父对象(父对象),p(新的OGRPoint())
{}
~outputgrpoint();
运算符OGRPoint*(){return p;}
outputgrpoint(outputgrpoint&&)=默认值;
outputgrpoint&运算符=(outputgrpoint&&)=默认值;
私人:
这是我的迭代器*父;
std::唯一的ptr p;
};
类这个是我的迭代器{
OutputAgrPoint运算符*()(返回OutputAgrPoint(this);}
私人:
朋友输出点;
无效应用运算符星号更改(OGRPoint*p);
};
内联OutputOGRPoint::~OutputOGRPoint()
{parent->apply_operator_star_changes(p);}
当您需要管理返回值生存期的代码时,可使用此“伪指针”返回类型。它还可用于“返回可变引用”用于实际不存在的内部成员。
vector
在内部使用位字段而不是bool
对象,但使用相同的模式从运算符[]
返回可变引用。这假设OGRPoint是可复制构造的。如果不是,请使用智能指针
#include <iterator>
#include <ogr_geometry.h>
struct OGR_SimpleCurve_Points_Iterator : std::iterator< std::random_access_iterator_tag, const OGRPoint >
{
OGR_SimpleCurve_Points_Iterator( OGRSimpleCurve* curve=nullptr, int index=0 )
: curve(curve), index(index) {}
OGR_SimpleCurve_Points_Iterator& operator++() { ++index; return *this; }
OGR_SimpleCurve_Points_Iterator operator++(int) { OGR_SimpleCurve_Points_Iterator ret(*this); ++index; return ret; }
OGR_SimpleCurve_Points_Iterator& operator--() { --index; return *this; }
OGR_SimpleCurve_Points_Iterator operator--(int) { OGR_SimpleCurve_Points_Iterator ret(*this); --index; return ret; }
OGR_SimpleCurve_Points_Iterator& operator+=(int n) { index+=n; return *this; }
OGR_SimpleCurve_Points_Iterator& operator-=(int n) { index-=n; return *this; }
OGR_SimpleCurve_Points_Iterator operator+(int n) { return OGR_SimpleCurve_Points_Iterator{curve,index+n}; }
OGR_SimpleCurve_Points_Iterator operator-(int n) { return OGR_SimpleCurve_Points_Iterator{curve,index-n}; }
int operator-(const OGR_SimpleCurve_Points_Iterator& other) { return index-other.index; }
OGRPoint operator*() { OGRPoint p; curve->getPoint(index,&p); return p; }
OGRPoint operator[](int ofs) { OGRPoint p; curve->getPoint(index+ofs,&p); return p; }
bool operator == ( const OGR_SimpleCurve_Points_Iterator& other ) { return index==other.index; }
bool operator != ( const OGR_SimpleCurve_Points_Iterator& other ) { return index!=other.index; }
bool operator > ( const OGR_SimpleCurve_Points_Iterator& other ) { return index >other.index; }
bool operator >= ( const OGR_SimpleCurve_Points_Iterator& other ) { return index>=other.index; }
bool operator < ( const OGR_SimpleCurve_Points_Iterator& other ) { return index <other.index; }
bool operator <= ( const OGR_SimpleCurve_Points_Iterator& other ) { return index<=other.index; }
private:
OGRSimpleCurve* curve;
int index;
};
OGR_SimpleCurve_Points_Iterator begin( OGRSimpleCurve* curve )
{
return OGR_SimpleCurve_Points_Iterator{curve};
}
OGR_SimpleCurve_Points_Iterator end( OGRSimpleCurve* curve )
{
return OGR_SimpleCurve_Points_Iterator{curve,curve->getNumPoints()};
}
#包括
#包括
struct OGR\u SimpleCurve\u Points\u Iterator:std::Iterator
{
OGR\u SimpleCurve\u Points\u迭代器(OGRSimpleCurve*curve=nullptr,int index=0)
:曲线(曲线),索引(索引){}
OGR_SimpleCurve_Points_迭代器和运算符++(){++index;返回*this;}
OGR_SimpleCurve_Points_迭代器运算符++(int){OGR_SimpleCurve_Points_迭代器ret(*this);++索引;返回ret;}
OGR_SimpleCurve_Points_迭代器和运算符--(){--index;return*this;}
OGR_SimpleCurve_Points_迭代器运算符--(int){OGR_SimpleCurve_Points_迭代器ret(*this);--索引;返回ret;}
OGR_SimpleCurve_Points_迭代器和运算符+=(int n){index+=n;返回*this;}
OGR_SimpleCurve_Points_迭代器和运算符-=(int n){index-=n;返回*this;}
OGR_SimpleCurve_Points_迭代器运算符+(int n){返回OGR_SimpleCurve_Points_迭代器{曲线,索引+n};}
OGR_SimpleCurve_Points_迭代器运算符-(int n){返回OGR_SimpleCurve_Points_迭代器{曲线,索引-n};}
int运算符-(const OGR_SimpleCurve_Points_Iterator&other){return index-other.index;}
OGRPoint操作符*(){OGRPoint p;曲线->获取点(索引,&p);返回p;}
OGRPoint操作符[](intofs){OGRPoint p;curve->getPoint(index+ofs,&p);返回p;}
布尔运算符==(const OGR\u SimpleCurve\u Points\u Iterator&other){return index==other.index;}
布尔运算符!=(const OGR\u SimpleCurve\u Points\u Iterator&other){return index!=other.index;}
布尔运算符>(const OGR_SimpleCurve_Points_Iterator&other){return index>other.index;}
布尔运算符>=(const OGR\u SimpleCurve\u Points\u Iterator&other){return index>=other.index;}
bool操作符<(const OGR_SimpleCurve_Points_Iterator&other){返回索引您应该看看如何vector::operator[]
有效,这将向您展示如何解决这个怪癖。您现在正在做什么导致内存泄漏?为什么迭代器没有管理OGRPoint
?迭代器做什么?OGRPoint可以与值语义一起使用吗?即它有复制构造函数等?在这种情况下,请这样做,而不是“新建”。如果没有,请使用smartpointersTha非常感谢!经过相当多的工作(并阅读了与C++相关的技巧),这个版本最适合我的需要。复制可构造指针对共享指针对原始指针的评论最终让我真正理解了我所面临的问题。再次感谢!这看起来像一个完整的迭代器,但没有运算符->
,这个迭代器只满足输出迭代器的概念。它也是mi使用所有的typedef。如果添加这些,一个默认构造函数和操作符+(int,iterator)
,那么它就可以接收完整的随机访问迭代器标签。
。输出指针的概念对我来说是新的,非常感谢!多亏了你和sp2danny的回答,我学到了很多东西。我后来才看到这一点