![]() |
Home | Libraries | People | FAQ | More |
本節描述 BOOST_FOREACH 中的一些常見的缺陷。
由於 BOOST_FOREACH 是一個宏,它必須剛好有兩個參數,並以一個逗號分隔它們。這並不總是很方便,尤其當循環變量的類型是一個模板的時候。考慮一下對 std::map 進行迭代:
std::map<int,int> m; // 錯誤!BOOST_FOREACH 宏參數過多。
BOOST_FOREACH(std::pair<int,int> p, m) // ...
一個解決方法是使用 typedef.
std::map<int,int> m; typedef std::pair<int,int> pair_t; BOOST_FOREACH(pair_t p, m) // ...
另一個解決方法是預先聲明循環變量:
std::map<int,int> m; std::pair<int,int> p; BOOST_FOREACH(p, m) // ...
在內部,BOOST_FOREACH 使用了迭代器來遍歷序列的元素。在循環執行之前,結束迭代器會緩存到一個局部變量中。這被稱為 hoisting, 它是一個重要的優化。但是它假設該序列的結束迭代器是穩定的。通常也是這樣,但如果我們在迭代序列時增加或刪除了序列的元素,我們就可能自己破壞了 hoisting.
考慮以下代碼:
std::vector<int> vect(4, 4); BOOST_FOREACH(int i, vect) { vect.push_back(i + 1); }
這段代碼可以編譯,但它具有未定義行為。這是因為它在邏輯上等同於以下代碼:
std::vector<int> vect(4, 4); for(std::vector<int>::iterator it1 = vect.begin(), it2 = vect.end(); it1 != it2; ++it1) { int i = *it1; vect.push_back(i + 1); // Oops! 這使得 it1 和 it2 無效!
}
對 vect.push_back()
的調用會導致 vect
中的所有迭代器變為無效,包括 it1 和 it2. 循環的下一次迭代會使用這些無效迭代器。這可是壞消息。
正確的做法是,在迭代中增加或刪除序列中的元素一定要三思。如果這樣做會導致迭代器變為無效,就不要這樣做。用一個普通的 for
循環來替代。
| Copyright © 2004 Eric Niebler |