摘自:深入应用C++:代码优化与工程级应用
1.4.1 for循环的新用法
std::for_each()
使用std::for_each()做循环,不需要关心迭代器的概念,只需要关心容器的类型。如:
#include <algorithm>
void do_count(int n)
{
cout<<n<<endl;
}
vector<int> vect={1,2,3,4,5,6,7,8,9,0};
std::for_each(vect.begin(),vect.end(),do_count);
第三个参数可以用函数指针,也可以用lambda表达式。
基于范围的for循环
在C++11中,提供了基于范围的for循环。如:
vector<int> vect={1,2,3,4,5,6,7,8,9,0};
for(auto num:vect)
{
cout<<num<<endl;
}
对于冒号前面的局部变量声明,只要能够支持容器类型的隐式转换即可。如:
vector<long long int> vect={1,2,3,4,5,6,7,8,9,0};
for(int num:vect)
{
cout<<num<<endl;
}
如果要修改容器中的值,需要使用引用。如:
vector<int> vect={1,2,3,4,5,6,7,8,9,0};
for(int &num:vect)
{
num++;
cout<<num<<endl;
}
1.4.2 基于范围的for循环的使用细节
基于范围的for循环,与普通for循环一样,遵循容器本身的特性:
- 对于map容器,var(元素)的类型是:std:pair,需要使用var.first和var.second来提取键值。
- 对与map容器,var.first是只读的(const T&)。
- 对于set容器,var(元素)是只读的。
map<string,int> mm={{"Hello",1},{"World",2}};
for(pair<string,int> var:mm)
{
cout<<var.first<<" "<<var.second<<endl;
}
- 基于范围的for循环,冒号后面的表达式只会被计算一次。
- 基于范围的for循环,是普通for循环的语法糖。与普通for循环一样,迭代时修改容器可能会导致迭代器失效。
for(auto var:array)
{
cout<<var<<endl;
}
等价于:
for(auto begin=array.begin(),end=array.end();begin!=end;begin++)
{
cout<<*begin<<endl;
}
1.4.3 让基于范围的for循环支持自定义类型
为了使自定义的数据类型支持基于范围的for循环,需要定义begin和end迭代器。
编译器通过以下方式查找begin和end迭代器:
- 普通数组,begin为数组的首地址,end为首地址加数组长度。
- 类对象,查找内部的begin和end成员函数。
- 否则,试图使用全局的begin和end函数。