void funcX()
{
std::map<std::string, std::string> seasons;
seasons["spring"] = "123";
seasons["summer"] = "456";
seasons["autumn"] = "789";
seasons["winter"] = "101112";
for (std::map<std::string, std::string>::iterator iter = seasons.begin();iter != seasons.end();iter++)
{
std::cout << iter->second << std::endl;
}
}
void funcY()
{
std::map<std::string, std::string> seasons;
seasons["spring"] = "123";
seasons["summer"] = "456";
seasons["autumn"] = "789";
seasons["winter"] = "101112";
for (auto iter : seasons)
{
std::cout << iter.second << std::endl;
}
}
for-each语法虽然很强大,但是有两个需要注意的地方。
◎ for-each中的迭代器类型与数组或集合中元素的类型完全一致,而原来使用老式语法迭代 stl容器(如 std::map)时,迭代器 iter的类型是 stl容器中元素的指针类型。因此,在上面例子的老式语法中,iter是一个指针类型(std::pair<std::string,std::string>*),使用 iter->second 去引用键值;而在for-each 语法中,iter 与容器中元素的数据类型(std::pair<std::string,std::string>)相同,因此使用iter.second可直接引用键值。
◎ 在 for-each 语法中,对于复杂的数据类型,迭代器是原始数据的拷贝,而不是原始数据的引用。
对于容器中的复杂数据类型,我们应该尽量使用引用原始数据的方式,减少不必要的拷贝构造函数调用开销。
#include<iostream>
#include<string>
template<typename T,size_t N>
class A
{
public:
A()
{
for (size_t i = 0; i < N; i++)
{
m_elements[i] = i;
}
}
~A()
{}
T* begin()
{
return m_elements + 0;
}
T* end()
{
return m_elements + N;
}
private:
T m_elements[N];
};
int main()
{
A<int, 10> a;
for (auto iter : a)
{
std::cout << iter << std::endl;
}
return 0;
}
自定义对象支持Range-based循环语法至少需要实现如下两个方法:
1、需要返回第1个迭代子的位置
Iterator begin();
2、需要返回最后一个迭代子的下一个位置
Itera end();
上面的Iterator是自定义数据类型的迭代子类型,这里的Iterator类型必须支持如下三种操作。
◎ operator++(自增)操作,可以在自增之后返回下一个迭代子的位置。
◎ operator!=(判不等操作)操作。
◎ operator*(解引用,dereference)操作。
在这个循环中,begin-expr返回的迭代子__begin 需要支持自增操作,且每次循环时都会与end-expr返回的迭代子__end做判不等比较,在循环内部通过调用迭代子的解引用(*)操作取得实际的元素。这就是上文说的迭代子对象需要支持operator++、operator!=和operator*的原因了