注意算法accumulate并不位于algorithm这个库文件中,它和其他三个“数值算法”存在于中,另外的三个算法依次是inner_product/adjacent_difference/partial_sum。
#include<iostream>
#include<algorithm>
#include<numeric>
#include<list>
#include<iterator>
#include<vector>
using namespace std;
int stringLenSum(int stringNowSum, const string& s)
{
return stringNowSum + s.size();
}
struct Point{
Point(double initx, double inity) :x(initx), y(inity){};
double x;
double y;
};
class PointAverage :
public binary_function<Point, Point, Point>{
public:
PointAverage() :xSUm(0), ySUm(0), numPoints(0){};
const Point operator()(const Point& avgSoFar, const Point& p)
{
++numPoints;
xSUm += p.x;
ySUm += p.y;
return Point(xSUm / numPoints, ySUm / numPoints);
}
private:
int numPoints;
double xSUm;
double ySUm;
};
class PointAverageForEach :
public binary_function<Point, Point, Point>{
public:
PointAverageForEach() :xSUm(0), ySUm(0), numPoints(0){};
const Point operator()(const Point& avgSoFar, const Point& p)
{
++numPoints;
xSUm += p.x;
ySUm += p.y;
}
Point result() const
{
return Point(xSUm / numPoints, ySUm / numPoints);
}
private:
int numPoints;
double xSUm;
double ySUm;
};
int main()
{
list<double> ld;
for (int i = 1; i <= 10; i++)
{
ld.push_back(i+0.4987);
}
double sumDouble = accumulate(ld.begin(), ld.end(), 0.0);
double sumInt = accumulate(ld.begin(), ld.end(), 0);
cout << sumDouble << endl;//输出为59.987,输出为double
cout << sumInt << endl;//输出为59,因为初始化为0,所以是把每次的加法都转化为整数之后的总和
//下边这段代码不太明白在干什么
cout << "The sum of the ints on the standard input is:"
<< accumulate(istream_iterator<int>(cin), istream_iterator<int>(), 0)
<< endl;
//下边这段代码演示用accumulate来计算字符串的总长度
list<string> ss;
//对ss的插入操作
int sumLen = accumulate(ss.begin(), ss.end(), static_cast<int>(0), stringLenSum);
vector<float> vf;
float sumFloat = accumulate(vf.begin(), vf.end(), 1.0f, multiplies<float>());
//下边是计算一个区间中所有点的平均值,这是使用的accumulate的方法
list<Point> lp;
Point avg = accumulate(lp.begin(), lp.end(), Point(0, 0), PointAverage());
//下边是使用for_each的用法
Point avg = for_each(lp.begin(), lp.end(), PointAverageForEach().result());
return 0;
}
这工作得很好,而且仅因为我有时候和一些非常狂热的人打交道(他们中的很多都在标准委员会),所以我
才会预见到它可能失败的STL实现。不过,PointAverage和标准的第26.4.1节第2段冲突,我知道你想起来了,
那就是禁止传给accumulate的函数中有副作用。成员变量numPoints、xSum和ySum的修改造成了一个副作用,
所以,技术上讲,我刚展示的代码会导致结果未定义。实际上,很难想象它无法工作,但当我这么写时我被
险恶的语言律师包围着,所以我别无选择,只能在这个问题上写出难懂的条文。
那很好,因为它给我了一个机会来提起for_each,另一个可以用于统计区间而且没有accumulate那么多限制的
算法。正如accumulate,for_each带有一个区间和一个函数(一般是一个函数对象)来调用区间中的每个元
素,但传给for_each的函数只接收一个实参(当前的区间元素),而且当完成时for_each返回它的函数。(实
际上,它返回它的函数的一个拷贝——参见条款38。)值得注意的是,传给(而且后来要返回)for_each的函
数可能有副作用。
除了副作用问题,for_each和accumulate的不同主要在两个方面。首先,accumulate的名字表示它是一个产生区
间统计的算法,for_each听起来好像你只是要对区间的每个元素进行一些操作,而且,当然,那是那个算法
的主要应用。用for_each来统计一个区间是合法的,但是它没有accumulate清楚。