本篇将对C++ 标准库中的两种foreach,以及boost中的BOOST_FOREACH进行讲解说明
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <boost/foreach.hpp>
// 遍历STL标准库容器
int main()
{
std::vector<int> vec{ 1,2,3,4,5 };
// 1. C++ 中标准用法
for (int &num : vec)
{
num *= 2;
}
// 2. algorithm 中的 for_each
std::for_each(begin(vec), end(vec), [](int num) {std::cout << num << " "; }); // 写法1
std::cout << std::endl;
std::for_each(vec.cbegin(), vec.cend(), [](int num) {std::cout << num << " "; }); // 写法2, 多一个c前缀表示const
std::cout << std::endl;
std::for_each(vec.rbegin(), vec.rend(), [](int num) {std::cout << num << " "; }); // 反向遍历,r前缀表示反向,r和c可以组合使用
std::cout << std::endl;
/*
这种写法可能被废弃了,在VS2017下报错
for each (object var in collection_to_loop)
{
}
*/
// 3.BOOST_FOREACH
// 与第1种用法类似 for(object var: collection_to_loop)
BOOST_FOREACH(int &num, vec) // 可以使用引用访问
{
num += 1;
}
int num;
BOOST_FOREACH(num, vec) // 可以将 int num 定义写在外边
{
std::cout << num << " ";
}
std::cout << "\n";
// 反向遍历
BOOST_REVERSE_FOREACH(const auto & num, vec) // 可以写int num, auto num, const int num, int &num等,都没有问题
{
std::cout << num << " ";
}
std::cin.get();
return 0;
}
以下是官方提供的 Range-based for Statement (C++) 示例代码
// range-based-for.cpp
// compile by using: cl /EHsc /nologo /W4
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// Basic 10-element integer array.
int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Range-based for loop to iterate through the array.
for( int y : x ) { // Access by value using a copy declared as a specific type.
// Not preferred.
cout << y << " ";
}
cout << endl;
// The auto keyword causes type inference to be used. Preferred.
for( auto y : x ) { // Copy of 'x', almost always undesirable
cout << y << " ";
}
cout << endl;
for( auto &y : x ) { // Type inference by reference.
// Observes and/or modifies in-place. Preferred when modify is needed.
cout << y << " ";
}
cout << endl;
for( const auto &y : x ) { // Type inference by reference.
// Observes in-place. Preferred when no modify is needed.
cout << y << " ";
}
cout << endl;
cout << "end of integer array test" << endl;
cout << endl;
// Create a vector object that contains 10 elements.
vector<double> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i + 0.14159);
}
// Range-based for loop to iterate through the vector, observing in-place.
for( const auto &j : v ) {
cout << j << " ";
}
cout << endl;
cout << "end of vector test" << endl;
}
经过测试,将上边示例中for换成BOOST_FOREACH, for中的冒号换成逗号,发现程序仍然正常运行,说明两者是等价的。
下面列举一些BOOST_FOREACH的用法示例
1. 可访问std::string
#include <string>
#include <iostream>
#include <boost/foreach.hpp>
int main()
{
std::string hello( "Hello, world!" );
BOOST_FOREACH( char ch, hello )
{
std::cout << ch;
}
return 0;
}
2.支持C风格的数组,下面是一些示例展示了BOOST_FOREACH的基本用法
#include <iostream>
#include <vector>
#include <boost/foreach.hpp>
#include <list>
#include <queue>
using namespace std;
void main()
{
// 1. 访问STL容器
std::list<int> list_int{ 1,2,3,4 };
BOOST_FOREACH(int i, list_int)
{
// do something with i
}
// 2. 可以访问C风格的数组
short array_short[] = { 1,2,3 };
BOOST_FOREACH(int i, array_short)
{
// The short was implicitly converted to an int
}
// 3. int i可前向定义,BOOST_FOREACH 支持关键字continue,break,return
std::deque<int> deque_int{ 4,5,6,1,7,8,2,9 };
//std::deque<int> deque_int{ 4,5,6,1,7,8,0,9 };
int i = 0;
BOOST_FOREACH(i, deque_int)
{
if (i == 0) return;
if (i == 1) continue;
if (i == 2) break;
std::cout << i << " ";
}
// 4. 引用访问C数组
short array_short[] = { 1, 2, 3 };
BOOST_FOREACH(short & i, array_short)
{
++i;
}
// array_short[] = { 2, 3, 4 };
// 5. 使用嵌套的BOOST_FOREACH, 此处可以发现,BOOST_FOREACH的大括号不是必须的
std::vector<std::vector<int> > matrix_int;
BOOST_FOREACH(std::vector<int> & row, matrix_int)
BOOST_FOREACH(int & i, row)
++i;
// 6. 循环体中可以是一个函数,函数返回值是要遍历的容器
extern std::vector<float> get_vector_float();
BOOST_FOREACH(float f, get_vector_float())
{
// 注意:此处的 get_vector_float() 函数只会被调用一次
// 可以这样测试:让函数get_vector_float()每一次调用都返回不一样的值
}
// 7. 反向遍历
std::list<int> list_int( /*...*/);
BOOST_REVERSE_FOREACH(int i, list_int)
{
// do something with i
}
std::cin.get();
}
有一点需要注意的是,有时候我们觉得BOOST_FOREACH写起来比较长,不方便,于是我们就定义了以下的宏来代替BOOST_FOREACH:
#define foreach BOOST_FOREACH
于是有了下面的代码
#include <iostream>
#include <boost/foreach.hpp>
//using namespace boost;
#define foreach BOOST_FOREACH
void main()
{
int arr[]{ 1,2,3,4,5 };
foreach(int i, arr)
{
std::cout << i << " ";
}
std::cin.get();
}
运行起来确实也没问题,但是官方推荐尽量使用下面的宏定义
#define foreach_ BOOST_FOREACH
#define foreach_r_ BOOST_REVERSE_FOREACH
因为在boost/foreach.hpp中foreach是一个namespace,有很多人宏都是用的 #define foreach BOOST_FOREACH,这样可能会出问题,我测试了当我using namespace boost 后,程序仍然正确运行,但并不表示所有情况都正确,因为foreach是一个比较常用的关键词,比如在Qt 中也有foreach,这样在某些情况下可能会有未知的错误,所以推荐使用带下划线的foreach宏定义
// boost/foreach.hpp
namespace foreach
{
///
// in_range
//
template<typename T>
inline std::pair<T, T> in_range(T begin, T end)
{
return std::make_pair(begin, end);
}
//.....
} // namespace foreach