// <algorithm> 
template <class InputIterator, class Function>
    Function for_each (InputIterator first,
​        InputIterator last, Function fn);

对范围中的每个元素调用指定函数。

该函数等价于:

template<class _InIt,
    class _Fn1> inline
    void _For_each(_InIt _First, _InIt _Last, _Fn1& _Func)
    {    // perform function for each element
        for (; _First != _Last; ++_First)
            _Func(*_First);
    }

template<class _InIt,
    class _Fn1> inline
    _Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
    {   // perform function for each element
        _For_each(_Unchecked(_First), _Unchecked(_Last), _Func);
        return (_STD move(_Func));
    }
  • firstlast

    分别指向一个序列中初始及末尾位置的输入迭代器。这个范围即 [first,last) ,包括 first 到 last 间的所有元素,包括 first 指向的元素,但不包括 last 指向的元素。

    fn

    一元谓词(Unary)函数,以范围中的一个元素为参数。

    可以是函数指针(Function pointer)类型或函数对象(Function object)类型。

    返回

    C++ 98

    返回 fn

    C++ 11

    返回 fn,类似于调用 std::move(fn)

  • 例 1

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    namespace ClassFoo{
        // 打印每个元素
        void PrintVectorFun(int i) {  // function:
            std::cout << i << ' ';
        }
        // 使用函数对象,打印每个元素
        struct PrintVectorStruct {           // function object type:
            void operator() (int i) { std::cout << i << ' '; }
        } PrintVectorObject;
    
        void ForEach_1() {
            std::vector<int> MyVector;
            MyVector.push_back(22);
            MyVector.push_back(4);
            MyVector.push_back(9);
            MyVector.push_back(234);
            // 使用普通函数打印
            std::for_each(MyVector.begin(), MyVector.end(), PrintVectorFun);
            std::cout << std::endl;
            // 使用函数对象打印
            std::for_each(MyVector.begin(), MyVector.end(), PrintVectorObject);
            std::cout << std::endl;
        }
    }
    int main()
    {
        ClassFoo::ForEach_1();
        std::cin.get();
        return 0;
    }

    22 4 9 234 
    22 4 9 234 

    例 2

    旧版 C++ 中,使用 for_each 操作对象数组、对象指针数组的方法

    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm>
    #include <functional>
    #include <sstream>
    
    namespace ClassFoo{
        using namespace std;
        class Person {
        private:
            std::string name;
            static int n;
        public:
            Person() {
                std::stringstream ss;
                std::string snum;
                ss << n++;
                ss >> snum;
                name = "foo" + snum;
            }
            void print() const {
                std::cout << name << std::endl;
            }
            void printWithPrefix(std::string prefix) const {
                std::cout << prefix << name << std::endl;
            }
        };
    
        int Person::n = 0;
    
        void foo(const std::vector<Person>& coll)
        {
            // 对每个元素对象调用成员函数 print()
            for_each(coll.begin(), coll.end(), mem_fun_ref(&Person::print));
    
            // 对每个元素对象调用成员函数 printWithPrefix()
            // - "person: " 作为参数传递给成员函数
            for_each(coll.begin(), coll.end(),
                bind2nd(mem_fun_ref(&Person::printWithPrefix), "person: "));
        }
    
        void ptrfoo(const std::vector<Person*>& coll)
        {
            // 对每个指针指向的元素对象调用成员函数 print()
            for_each(coll.begin(), coll.end(),
                mem_fun(&Person::print));
    
            // 对每个指针指向的元素对象调用成员函数 printWithPrefix()
            // - "person: " 作为参数传递给成员函数
            for_each(coll.begin(), coll.end(),
                bind2nd(mem_fun(&Person::printWithPrefix), "person: "));
        }
        void ForEach_2() {
            std::cout << "当向量的元素是对象时:" << std::endl;
            std::vector<ClassFoo::Person> coll(5);
            ClassFoo::foo(coll);
    
            std::cout << "当向量的元素是指向对象的指针时:" << std::endl;
            std::vector<ClassFoo::Person*> coll2;
            coll2.push_back(new ClassFoo::Person);
            coll2.push_back(new ClassFoo::Person);
            coll2.push_back(new ClassFoo::Person);
            coll2.push_back(new ClassFoo::Person);
            coll2.push_back(new ClassFoo::Person);
            ptrfoo(coll2);
        }
    }
    int main()
    {
        ClassFoo::ForEach_2();
        return 0;
    }

    当向量的元素是对象时:foo0
    foo1
    foo2
    foo3
    foo4
    person: foo0
    person: foo1
    person: foo2
    person: foo3
    person: foo4
    当向量的元素是指向对象的指针时:
    foo5
    foo6
    foo7
    foo8
    foo9
    person: foo5
    person: foo6
    person: foo7
    person: foo8
    person: foo9

    例 3

    C++11

    使用 lambda 表达式

    // 使用lambda表达式使每个元素加1
    std::for_each(nums.begin(), nums.end(), [](int &n){ n++; });

    例4

    遍历操作文件内容

    std::ifstream infile("classfoo.com.txt");
    std::for_each(std::istream_iterator<std::string>(infile),std::istream_iterator<std::string>(),
            SomeFunc());
  • 复杂度

    O(n)n last first,执行过程中对每个元素调用 fn

    数据争用相关

    访问在范围 [first,last) 中的所有元素,且每个元素确定只被访问一次。

    如果输入迭代器(Input Iterator)是一个可变迭代器(即非 const),且 fn 不是一个常函数,那么元素可能会被修改。

    异常安全性相关

    如果 fn 或操作某个迭代器抛异常,该函数才会抛异常。

    注意 无效参数将导致未定义行为(Undefined behavior)