本篇將對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