首先,这里说的for循环,是指C++中新增的for(a : b)格式的for循环。
最近碰到了这样的问题,就来记录一下。如有错漏,还望指摘。
C++新增的这种for循环,使用来遍历容器中的每一个元素。但是有时候,我想自定义自己的容器,那能不能也使用这样的for循环呢?
答案肯定是可以的。那么需要什么要求呢?
for循环的大致逻辑
要向弄明白有什么需求,我们首先需要弄明白,这个for循环是怎么实现的。
比如对于for(ele : list)
, 其实大致相当于如下代码:
for(auto it = list.begin(); it != list.end(); ++it)
{
ele = *it;
// ......
}
自定义for循环要求
那么我们就可以看出对于格式为for(ele : list)
的for循环语句,有如下要求
- 变量list对应的类型中必须包含begin()函数
- 变量list对应的类型中必须包含end()函数
- begin()函数的返回值类型中,必须实现了++操作符
- begin()函数的返回值类型中,必须实现了*操作符
- begin()函数的返回值类型中,必须实现了参数类型为end()函数返回值类型的!=操作符。
实现
所以如下代码就可以实现自定义for循环:
class ArrayEnd
{
public:
int* ptr_;
ArrayEnd(int* ptr) : ptr_(ptr) {}
};
class ArrayBegin
{
private:
int* ptr_;
public:
ArrayBegin(int* ptr) : ptr_(ptr) {}
ArrayBegin& operator++()
{
ptr_++;
return *this;
}
int& operator *() { return *ptr_; }
bool operator != (const ArrayEnd& e) { return ptr_ != e.ptr_; }
};
class myArray
{
private:
int* ptr_;
int len_;
public:
myArray(int* ptr, int len) : ptr_(ptr), len_(len) {}
ArrayBegin begin() { return ArrayBegin(ptr_); }
ArrayEnd end() { return ArrayEnd(ptr_ + len_); }
};
不过当然,一般我们会将ArrayBegin和ArrayEnd合并在一起成为ArrayIterator:
class ArrayIterator
{
private:
int* ptr_;
public:
ArrayIterator(int* ptr) : ptr_(ptr) {}
ArrayIterator& operator++()
{
ptr_++;
return *this;
}
int& operator *() { return *ptr_; }
bool operator != (const ArrayIterator& e) { return ptr_ != e.ptr_; }
};
class myArray
{
private:
int* ptr_;
int len_;
public:
myArray(int* ptr, int len) : ptr_(ptr), len_(len) {}
ArrayIterator begin() { return ArrayIterator(ptr_); }
ArrayIterator end() { return ArrayIterator(ptr_ + len_); }
};