目录
1. 语法定义
C++11新增范围for语法
for (declaration : exporession)
statement
exporession:定义序列对象,即包含 begin()/end(),以及对应迭代器
declaration:定义一个变量,其类型可以是序列成员,也可以是通过序列成员转换获得
如
for (auto item : v)
statement
按书上解释,其等同于
for (auto item = v.begin(), end = v.end(); beg != end; ++beg)
statement
但二者在item类型上,有本质的区别,经实验,其语法应等效于
{ //< 加{},确保创建的是临时变量
auto beg = v.begin(), end = v.end();
for (decltype(*v.begin()) item; beg != end && (item = *beg, true); ++beg)
statement
}
因此,item的类型是实际容器元素的类型,且可以使用功能 const auto & 进行变化,避免拷贝。
2. 测试代码
class IntVector;
class Iter
{
private:
int _pos;
const IntVector* _p_vec;
public:
Iter(const IntVector* p_vec, int pos)
: _pos(pos), _p_vec(p_vec)
{
std::cout << __FUNCTION__ << std::endl;
}
bool operator!=(const Iter& other) const
{
std::cout << __FUNCTION__ << std::endl;
return _pos != other._pos;
}
int operator*() const;
const Iter& operator++()
{
std::cout << __FUNCTION__ << std::endl;
++_pos;
return *this;
}
};
class IntVector
{
private:
int _data[100] = { 0 };
public:
IntVector() {}
int get(int col) const
{
std::cout << __FUNCTION__ << std::endl;
return _data[col];
}
Iter begin() const
{
std::cout << __FUNCTION__ << std::endl;
return Iter(this, 0);
}
Iter end() const
{
std::cout << __FUNCTION__ << std::endl;
return Iter(this, 100);
}
void set(int index, int val)
{
std::cout << __FUNCTION__ << std::endl;
_data[index] = val;
}
};
int Iter::operator*() const
{
std::cout << __FUNCTION__ << std::endl;
return _p_vec->get(_pos);
}
int main()
{
IntVector vct;
int i = 0;
for (const auto& it : vct)
{
printf("===========\r\n");
printf("%d\r\n", it);
//! 设置循环两遍
if ((++i) == 2)
{
break;
}
}
system("pause");
return 0;
}
打印结果
IntVector::begin
Iter::Iter
IntVector::end
Iter::Iter
Iter::operator !=
Iter::operator *
IntVector::get
===========
0
Iter::operator ++
Iter::operator !=
Iter::operator *
IntVector::get
===========
0
请按任意键继续. . .
3. 执行流程解释
第一遍循环,需要创建循环用的变量
IntVector::begin ——1.beg = vct.begin()
Iter::Iter ——2.beg 构造函数
IntVector::end ——3.end = vct.end()
Iter::Iter ——4.end 构造函数
Iter::operator != ——5.beg != end
Iter::operator * ——6.item = *beg
IntVector::get ——7.*beg,调用容器,获取元素
第二遍循环,更新beg和item
Iter::operator ++ ——1.++beg
Iter::operator != ——2.beg != end
Iter::operator * ——3.item = *beg
IntVector::get ——4.*beg,调用容器,获取元素
4. 等效旧标准代码
{
int i = 0;
IntVector v;
auto beg = v.begin(), end = v.end();
for (decltype(*v.begin()) item; beg != end && (item = *beg, true); ++beg)
{
printf("===========\r\n");
printf("%d\r\n", item);
//! 设置循环两遍
if ((++i) == 2)
{
break;
}
}
}
判断语句,增加 (item = *beg, true),使item的赋值,在beg!=end判定通过后执行,避免异常。