由于for_each接受的函数只接受一个参数(向量的元素),我必须在某处定义static int sum = 0
以便可以访问它
在调用for_each之后。我觉得这很尴尬。有没有更好的方法(仍然使用for_each)?
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
static int sum = 0;
void add_f(int i )
{
sum += i * i;
}
void test_using_for_each()
{
int arr[] = {1,2,3,4};
vector<int> a (arr ,arr + sizeof(arr)/sizeof(arr[0]));
for_each( a.begin(),a.end(), add_f);
cout << "sum of the square of the element is " << sum << endl;
}
在Ruby中,我们可以这样做:
sum = 0
[1,2,3,4].each { |i| sum += i*i} #local variable can be used in the callback function
puts sum #=> 30
请您展示更多示例for_each
如何在实际编程中使用(不只是打印出每个元素)?是否可以使用for_each
模拟'编程模式'喜欢用Ruby映射和注入(或在Haskell中映射/折叠)。
#map in ruby
>> [1,2,3,4].map {|i| i*i}
=> [1, 4, 9, 16]
#inject in ruby
[1, 4, 9, 16].inject(0) {|aac ,i| aac +=i} #=> 30
编辑:谢谢大家。我从你的回复中学到了很多东西。我们有很多方法可以在C ++中做同样的事情,这使得它有点难以学习。但它很有意思:))
答案 0 :(得分:36)
不,不要使用std :: accumulate()使用std :: inner_product()。不需要仿函数。
#include <vector>
#include <numeric>
void main()
{
std::vector <int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
int x = std::inner_product( v1.begin(), v1.end(), v1.begin(), 0 );
}
答案 1 :(得分:21)
#include <vector>
#include <numeric>
// functor for getting sum of previous result and square of current element
template<typename T>
struct square
{
T operator()(const T& Left, const T& Right) const
{
return (Left + Right*Right);
}
};
void main()
{
std::vector <int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
int x = std::accumulate( v1.begin(), v1.end(), 0, square<int>() );
// 0 stands here for initial value to which each element is in turn combined with
// for our case must be 0.
}
您可以在nice GMan's answer中模拟std :: accumulate,但我相信使用std :: accumulate会使您的代码更具可读性,因为它是为此目的而设计的。您可以找到更多标准算法here。
答案 2 :(得分:7)
for_each
返回它正在使用的仿函数(的副本)。所以,像这样:
#include <algorithm>
#include <vector>
#include <iostream>
template <typename T>
class square_accumulate
{
public:
square_accumulate(void) :
_sum(0)
{
}
const T& result(void) const
{
return _sum;
}
void operator()(const T& val)
{
_sum += val * val;
}
private:
T _sum;
};
int main(void)
{
int arr[] = {1,2,3,4};
std::vector<int> a (arr ,arr + sizeof(arr)/sizeof(arr[0]));
int sum = std::for_each(a.begin(), a.end(), square_accumulate<int>()).result();
std::cout << "sum of the square of the element is " << sum << std::endl;
}
正如其他答案所证明的那样,std::accumulate
是最佳方式。
答案 3 :(得分:4)
请勿使用for_each()
,使用accumulate()
标题中的<numeric>
:
#include <numeric>
#include <iostream>
using namespace std;
struct accum_sum_of_squares {
// x contains the sum-of-squares so far, y is the next value.
int operator()(int x, int y) const {
return x + y * y;
}
};
int main(int argc, char **argv) {
int a[] = { 4, 5, 6, 7 };
int ssq = accumulate(a, a + sizeof a / sizeof a[0], 0, accum_sum_of_squares());
cout << ssq << endl;
return 0;
}
accumulate()
的默认行为是对元素求和,但你可以像我们这样提供你自己的函数或函子,它执行的操作不需要是关联的 - 第二个参数总是下一个元素要操作。此操作有时在其他语言中称为reduce
。
您可以使用普通函数而不是accum_sum_of_squares
仿函数,或者为了更加通用,您可以使accum_sum_of_squares
成为接受任何数字类型的类模板。
答案 4 :(得分:3)
作为STL问题的一般解决方案:您可以传递functor
- 例如,实现operator()
的任何类的实例,而不是传递函数。这比依赖全局变量要好得多,因为所述实例可以保持并更新自己的状态!你可以把它想象成一种“编译时鸭子打字”:泛型编程不会限制你在那个地方传递一个“函数”,任何“表现得像一个函数”的东西(即,有一个合适的{{1} })也会这样做! - )
答案 5 :(得分:3)
std::for_each
用于对每个元素执行某些操作。如果你想从所有元素的计算得到一个结果,那就是std::accumulate
。如果您想要Haskell的map
行为,请使用std::transform
。
你可以滥用这三个中的任何一个来做与其他任何一个相同的事情,因为最终它们只是迭代迭代器(除了transform
的形式,它将两个迭代器作为输入。)关键是for_each
不是map / fold的替代 - 应该通过transform / accumulate来完成 - 尽管C ++本身没有表达map / fold概念以及Haskell的东西 - 但是这两个都是gcc和VC ++支持OpenMP,它在#pragma omp parallel for
中有更好的模拟。
在Ruby中注入与使用完整仿函数调用for_each
非常接近,如上面所解释的GMan。在C ++ 0X中使用变量捕获的Lambda函数将使两种语言之间的行为更加相似:
int main(void)
{
int arr[] = {1,2,3,4};
std::vector<int> a (arr ,arr + sizeof(arr)/sizeof(arr[0]));
int sum = 0;
std::for_each(a.begin(), a.end(), [&](int i) { sum += i*i;} );
std::cout << "sum of the square of the element is " << sum << std::endl;
}