为什么for_each不能修改其仿函数参数?

时间:2010-01-20 14:34:21

标签: c++ stl foreach

  

http://www.cplusplus.com/reference/algorithm/for_each/
  采用元素的一元函数   范围作为参数。这可以   是指向函数或函数的指针   类重载的对象   运算符()。它的返回值,如果有的话,   被忽略了。

根据这篇文章,我预计for_each实际上会修改作为第三个参数给出的对象,但似乎for_each在一个临时对象上运行,甚至不会修改给它的对象。

那么,为什么以这种方式实施呢?它似乎没那么有用。或者我误解了什么,下面的代码包含错误?

#include <iostream>
#include <vector>
#include <algorithm>

template <class T> struct Multiplicator{
    T mresult;
  public:
    const T& result() const{return mresult;}
    Multiplicator(T init_result = 1){
      mresult = init_result;
    }
    void operator()(T element){
      mresult *= element;
      std::cout << element << " "; // debug print
    }
};

int main()
{
    std::vector<double> vec;
    vec.push_back(1);
    vec.push_back(2);
    vec.push_back(3);
    Multiplicator<double> multiply;
    std::for_each(vec.begin(),vec.end(),multiply);
    std::cout << "\nResult: " << multiply.result() << std::endl;
    return 0;
}

预期产出:

1 2 3 Result: 6

但得到了以下输出:

1 2 3 Result: 1

3 个答案:

答案 0 :(得分:15)

函数对象按值获取。 for_each返回函数对象,因此如果将其更改为:

multiply = std::for_each(vec.begin(),vec.end(),multiply);

你得到了预期的输出。

答案 1 :(得分:10)

虽然詹姆斯是正确的,但使用std::accumulatestd::multiplies会更正确,可能是:

#include <iostream>
#include <functional>
#include <numeric>
#include <vector>

int main(void)
{
    std::vector<double> vec;
    vec.push_back(1);
    vec.push_back(2);
    vec.push_back(3);

    double result = std::accumulate(vec.begin(), vec.end(),
                                    1.0, std::multiplies<double>());

    std::cout << "\nResult: " << result << std::endl;

}

使用for_each版本,您不需要再次复制仿函数,而是:

double result = std::for_each(vec.begin(), vec.end(), multiply).result();

或C ++ 0x,为了好玩:

double result = 1;
std::for_each(vec.begin(), vec.end(), [&](double pX){ result *= pX; });

答案 2 :(得分:0)

For_each的语义不适合你想要做的事情。 accumulate正是你正在尝试的,而是使用它。