0.引入
for_each()算法非常灵活,它允许你以不同的方式访问、处理、修改每一个元素. 然而请注意,自C++11起,range-based for循环提供了更方便更自然的行为. 因此,for_each()恐将日渐丧失其重要性.
链接:分析
1.函数原型
for_each的原型如下:
namespace std
{
template <typename Iterator, typename Operation>
Operation for_each (Iterator act, Iterator end, Operation op)
{
while (act != end) // as long as not reached the end
{
op(*act); // - call op() for actual element
++act; // - move iterator to the next element
}
return op;
}
}
2.函数的一些说明
UnaryProc for_each (InputIterator beg, InputIterator end, UnaryProc op)
(1)对区间[beg,end)中的每一个元素调用:op(elem);
(2)返回 op(它已在算法内部被改动过)的一个拷贝(副本).Since C++11, the returned op is moved;
(3)op可以改动元素。然而,与transform()之间的比较,后者具有相同能力,但行事稍有不同;
(4)op的任何返回值都会被忽略;
(5)复杂度:线性。调用op()共numElems次.
3.不修改元素程序实例
// 本文件:foreach1.cpp
// 编译方法:g++ foreach1.cpp -std=c++11 -o foreach1
#include "algostuff.hpp"
using namespace std;
void print(int elem)
{
cout << elem << ' ';
}
int main()
{
vector<int> coll;
INSERT_ELEMENTS(coll,1,9);
/* call print() for each element */
/*方法1 把每一个元素传给一个lambda,后者将它所获得的元素打印出来.*/
for_each (coll.cbegin(), coll.cend(), [](int elem){cout << elem << ' ';});
cout << endl;
/*方法2*/
for_each (coll.cbegin(), coll.cend(),print);
cout << endl;
/*方法3 C++11 range-based for*/
for (auto elem:coll)
{
cout << elem << ' ';
}
cout << endl;
}
4.修改元素的实例
// g++ foreach2.cpp -std=c++11 -o foreach2 -fpermissive
// 本文件是foreach2.cpp
#include "algostuff.hpp"
using namespace std;
#define NONE "\033[m"
#define YELLOW "\033[1;33m"
#define DASH "*********************************"
int main()
{
vector<int> coll1;
INSERT_ELEMENTS(coll1, 1, 9);
/* 每个元素加10 */
for_each(coll1.begin(), coll1.end(), [](int &elem) { elem += 10; });
PRINT_ELEMENTS(coll1);
/* 每个元素加第一个元素的值的拷贝 */
for_each(coll1.begin(), coll1.end(), [=](int &elem) { elem += *coll1.begin(); });
PRINT_ELEMENTS(coll1);
cout << YELLOW << DASH << NONE << endl;
vector<int> coll2;
INSERT_ELEMENTS(coll2, 1, 9);
/* 每个元素加10 */
for_each(coll2.begin(), coll2.end(), [](int &elem) { elem += 10; });
PRINT_ELEMENTS(coll2);
/* 每个元素加第一个元素的值的引用 */
for_each(coll2.begin(), coll2.end(), [&](int &elem) { elem += *coll2.begin(); });
PRINT_ELEMENTS(coll2);
}
5.利用for_each()的返回值
/*
展示如何利用for_each()的返回值,
for_each()有一个特殊性质就是它能返回其操作,我们可以利用这一特性,
处理和返回“置于该操作中的结果”
[muten003@wknode algo]$ g++ foreach3.cpp -std=c++11 -o foreach3
[muten003@wknode algo]$ ./foreach3
mean value: 4.5
*/
#include "algostuff.hpp"
using namespace std;
// function object to process the mean value
class MeanValue {
private:
long num; // number of elements
long sum; // sum of all element values
public:
// constructor
MeanValue () : num(0), sum(0) {
}
// function call
// - process one more element of the sequence
void operator() (int elem) {
num++; // increment count
sum += elem; // add value
}
// return mean value (implicit type conversion)
operator double() {
return static_cast<double>(sum) / static_cast<double>(num);
}
};
int main()
{
vector<int> coll;
INSERT_ELEMENTS(coll,1,8);
// process and print mean value
double mv = for_each (coll.begin(), coll.end(), // range
MeanValue()); // operation
cout << "mean value: " << mv << endl;
}