![]() |
Home | Libraries | People | FAQ | More |
Copyright c 2004 Eric Niebler
Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
「Make simple things easy.」
-- Larry Wall
BOOST_FOREACH 是什麼?
在C++中,寫一個循環去迭代一個序列是很單調的。我們可以用迭代器,這需要相當大量的代碼,或者可以用 std::for_each()
算法,將我們的循環體移到一個謂詞中,這樣並沒有減少代碼量,還使得我們的邏輯遠離於使用的地點。作為對比,其它一些語言,如 Perl,就提供了專門的 "foreach" 結構來自動進行這一過程。BOOST_FOREACH 正是在C++中的一個同樣作用的結構。它為我們迭代一個序列,不需要我們來直接處理迭代器或編寫謂詞。
BOOST_FOREACH 是為了易用性和高效性而設計的。它不進行動態的內存分配,沒有虛擬函數調用或通過函數指針的調用,也沒有令編譯器的優化器無法處理的調用。這樣可以生成近似於最優化的代碼;BOOST_FOREACH 的性能通常只比手工編寫的循環差幾個百分點。而且雖然 BOOST_FOREACH 是一個宏,但它是有良好行為的。它只會對其參數進行一次求值,不會有令人討厭的問題。
以下是一個例子,使用了 BOOST_FOREACH 來迭代一個 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; }
程序的輸出如下:
Hello, world!
BOOST_FOREACH 用於迭代某個序列。但是這個序列有什麼要求呢?由於 BOOST_FOREACH 是構建在 Boost.Range 之上的,所以它自動支持了那些被 Boost.Range
認可的序列。特定地,BOOST_FOREACH 可用於滿足 單遍區間概念 的類型。例如,我們可以將 BOOST_FOREACH 用於:
char 和 wchar_t)
![]() |
備註 |
|---|---|
|
對 STL 容器的支持是非常全面的;任何類似於 STL 的容器都可算在內。只要它有嵌套的 |
關於如何將 BOOST_FOREACH 用於其它類型,請見 可擴展性
一節。
以下是一些例子,示範了我們使用
BOOST_FOREACH 的幾種不同方式。
迭代一個 STL 容器:
std::list<int> list_int( /*...*/ ); BOOST_FOREACH( int i, list_int ) { // 用 i 執行某些操作
}
迭代一個數組,具有協變性(即迭代變量的類型與容器的元素類型不完全相同):
short array_short[] = {1,2,3}; BOOST_FOREACH( int i, array_short ) { // short 被隱式轉換為 int
}
預先聲明循環變量,並在循環體中使用 break,
continue, 和 return :
std::deque<int> deque_int( /*...*/ ); int i = 0; BOOST_FOREACH( i, deque_int ) { if( i == 0 ) return; if( i == 1 ) continue; if( i == 2 ) break; }
以引用方式迭代一個序列,並修改底層序列:
short array_short[] = { 1, 2, 3 }; BOOST_FOREACH( short & i, array_short ) { ++i; } // 現在 array_short 包含 {2,3,4}
用嵌套的 BOOST_FOREACH
循環迭代一個 vector 的 vector. 在這個例子中,注意並不需要在循環體外面使用括號:
std::vector<std::vector<int> > matrix_int; BOOST_FOREACH( std::vector<int> & row, matrix_int ) BOOST_FOREACH( int & i, row ) ++i;
迭代一個以值方式(即右值)返回一個序列的函數:
extern std::vector<float> get_vector_float(); BOOST_FOREACH( float f, get_vector_float() ) { // 注: get_vector_float() 只會被調用一次
}
以反序遍歷:
std::list<int> list_int( /*...*/ );
BOOST_REVERSE_FOREACH( int i, list_int )
{
// 用 i 來做一些操作
}
在一些舊的編譯器上,不能對右值進行迭代。請查看 可移植性 一節,看看你的編譯器是否支持。
BOOST_FOREACH 更漂亮
有的人對 BOOST_FOREACH 的名字有意見。它太長了。而且大寫字母看起來有點煩人。這可能是真的,但 BOOST_FOREACH 不過是遵從了 Boost 名字規則。但是這並不意味著你必須用它。如果你想使用一個不同的標識符(可能是 foreach),你只要:
#define foreach BOOST_FOREACH
#define reverse_foreach BOOST_REVERSE_FOREACH
你唯一要保證的是,你選用的標識符不會在你的代碼中引起名字衝突。
![]() |
備註 |
|---|---|
|
不要用 |
|
Last revised: November 02, 2008 at 13:06:18 GMT |