我实现了一个普通的类MyClass
,该类new
在内部分配了一个数组(我知道我可以使用STL容器,但是我试图了解它们的工作方式)。我还创建了一个迭代器子类,该子类能够对MyClass
对象的所有元素进行迭代:
class MyIterator : public iterator<forward_iterator_tag,int>
{
private:
int* data= nullptr;
int length;
int pointer=0;
int nullvalue=0;
public:
MyIterator(int* data, int length, bool end= false)
{
this->data= data;
this->length= length;
if(end)
pointer=-1;
}
~MyIterator()
{
delete[] data;
}
MyIterator& operator++()
{
if(pointer!= length-1)
{
pointer++;
}
else
{
pointer= -1;
}
return *this;
}
bool operator==(const MyIterator& other)
{
return pointer==other.pointer;
}
bool operator!=(const MyIterator& other)
{
return pointer!= other.pointer;
}
int& operator* ()
{
if(pointer==-1)
return nullvalue;
else
return data[pointer];
}
};
class MyClass
{
private:
int* data= nullptr;
int length= 100;
public:
MyClass()
{
data= new int[length];
for(int i=0; i<length;i++)
data[i]=i+1;
}
iterator<forward_iterator_tag,int> begin()
{
return MyIterator(data,length);
}
iterator<forward_iterator_tag,int> end()
{
return MyIterator(data,length,true);
}
};
虽然迭代器可以通过以下方式使用:
for(MyIterator i= MyClass_instance.begin(); i!=MyClass_instance.end();i++) {...}
如果我尝试将其与BOOST_FOREACH一起使用,它将无法正常工作:
BOOST_FOREACH(int i, MyClass_instance) {...}
这些是我得到的错误:
您通过std::iterator<>
按值返回迭代器来对迭代器进行切片。你不能这样做。
通过引用返回将避免切片问题,但会引入更严重的问题:它返回对临时对象的引用¹。
因此,通过按值返回实际的迭代器类型来修复它。
您的类型缺少const迭代器。
所有迭代器成员都不是const正确的。
另外,根据页面的可扩展性,您似乎需要添加
namespace boost {
template<> struct range_mutable_iterator<MyClass> {
typedef MyClass::MyIterator type;
};
template<> struct range_const_iterator<MyClass> {
typedef MyClass::MyConstIterator type;
};
}
对于您的迭代器类型,“三法则”实现存在严重麻烦(什么是“三法则”?)。
每当迭代器不存在时,您都将删除容器的数据。而且MyClass
它本身永远不会释放数据...
解决以上大多数问题(?):
#include <iterator>
#include <boost/foreach.hpp>
class MyClass
{
private:
int* data = nullptr;
int length = 100;
public:
class MyIterator : public std::iterator<std::forward_iterator_tag, int>
{
public:
MyIterator(int* data, int length, bool end = false)
{
this->data= data;
this->length= length;
if(end)
pointer=-1;
}
MyIterator& operator++()
{
if(pointer!= length-1) {
pointer++;
}
else {
pointer= -1;
}
return *this;
}
bool operator==(const MyIterator& other) const { return pointer==other.pointer; }
bool operator!=(const MyIterator& other) const { return pointer!= other.pointer; }
int& operator*() const
{
if(pointer==-1)
return nullvalue;
else
return data[pointer];
}
private:
value_type* data = nullptr;
int length;
int pointer = 0;
mutable value_type nullvalue = 0;
};
class MyConstIterator : public std::iterator<std::forward_iterator_tag, const int>
{
public:
MyConstIterator(int const* data, int length, bool end = false)
{
this->data= data;
this->length= length;
if(end)
pointer=-1;
}
MyConstIterator& operator++()
{
if(pointer!= length-1) {
pointer++;
}
else {
pointer= -1;
}
return *this;
}
bool operator==(const MyConstIterator& other) const { return pointer==other.pointer; }
bool operator!=(const MyConstIterator& other) const { return pointer!= other.pointer; }
int const& operator*() const
{
if(pointer==-1)
return nullvalue;
else
return data[pointer];
}
private:
value_type* data = nullptr;
int length;
int pointer = 0;
value_type nullvalue = 0;
};
public:
typedef MyIterator iterator_type;
typedef MyConstIterator const_iterator_type;
MyClass()
{
data= new int[length];
for(int i=0; i<length;i++)
data[i]=i+1;
}
~MyClass() {
delete[] data;
}
iterator_type begin() { return MyIterator(data,length); }
iterator_type end() { return MyIterator(data,length,true); }
const_iterator_type begin() const { return MyConstIterator(data,length); }
const_iterator_type end() const { return MyConstIterator(data,length,true); }
};
namespace boost {
template<> struct range_mutable_iterator<MyClass> {
typedef MyClass::MyIterator type;
};
template<> struct range_const_iterator<MyClass> {
typedef MyClass::MyConstIterator type;
};
}
#include <iostream>
int main()
{
MyClass c;
BOOST_FOREACH(int i, c) {
std::cout << i << "\n";
}
}
¹(除非您将迭代器存储在其他位置,但是由于许多原因,这将是一个巨大的反模式)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句