十九、使用accumulate或者for_each进行区间统计。
accumulate有两种形式
template <class InputIterator, class T>
T accumulate (InputIterator first, InputIterator last, T init);
template <class InputIterator, class T, class BinaryOperation>
T accumulate (InputIterator first, InputIterator last, T init, BinaryOperation binary_op);
最简单的作用就是求和
示例
int main(int argc, char const *argv[])
{
vector<double> v={1.1,2.2,3.3,4.4,5.5};
double sum=accumulate(v.begin(),v.end(),0.0);
cout<<sum<<endl;
return 0;
}
注意,最后一个参数表示求和的初始值,必须是0.0,如果写成0,那么最终的求和结果就是截断浮点数的结果
示例二、计算字符串数组中的字符创总长度
string::size_type sum(int sum, const string &s) {return s.size()+sum;}
int main(int argc, char const *argv[])
{
vector<string> vs={"1234", "56789", "qwert"};
double totallen=accumulate(vs.begin(), vs.end(), 0, sum);
cout<<totallen<<endl;
return 0;
}
for_each的形式如下
template <class InputIterator, class Function>
Function for_each (InputIterator first, InputIterator last, Function fn);
for_each就是对迭代器范围内中的每个元素执行 fn
最简单的应用就是打印元素,见博客https://blog.csdn.net/Master_Cui/article/details/112506239
从for_each的形式可以看出,函数对象的传参形式是值传递,返回值也是按值返回,不仅是for_each,所有的STL的函数对象的传参形式都是值传递。
所以,如果需要设计一个函数类的话,就需要满足两点:1、函数类不能太大,否则传参的时候拷贝复制成本太高。2、函数类不能使多态类,否则把子类对象传给基类参数时,子类对象的特有数据会丢失
template <typename T>
class funcimp
{
template <typename T2>
friend class func;
public:
funcimp(){cout<<__func__<<endl;}
virtual ~funcimp(){cout<<__func__<<endl;}
virtual void operator()(const T &val);
};
template <typename T>
void funcimp<T>::operator()(const T &val){
cout<<__func__<<endl;
}
template <typename T>
class func {
public:
func():spimpfunc_(make_shared<funcimp<T>>())
{
cout<<__func__<<endl;
}
~func(){cout<<__func__<<endl;}
void operator()(const T &val);
private:
shared_ptr<funcimp<T>> spimpfunc_;
};
template <typename T>
void func<T>::operator()(const T &val) {
spimpfunc_->operator()(val);
}
int main(int argc, char const *argv[])
{
vector<string> vs={"1234", "56789", "qwert"};
func<string> ft;
for_each(vs.begin(), vs.end(), ft);
return 0;
}
该示例只是为了说明,所以类模板funcimp中的operator()啥也没做
因为func要作为一个非多态类并且不能太大,所以将数据和多态部分用一个类封装起来,并在func中使用了智能指针指向该类的对象,使用智能指针主要是为了避免内存泄露
这样,func既满足两上述两点要求,也可以间接的多态,可扩展
二十一、如何设计一个判别式函数类
一个判别式是一个返回值为bool类型的函数对象。标准关联容器的比较函数就是判别式;对于像***_if以及各种与排序有关的算法,判别式往往也被作为参数来传递。
除了遵守二十中所提到的两点外,还要保证判别式函数类的operator()的返回值仅仅依赖传入的参数(假设f是一个纯函数,x和y是两个对象,那么只有当x或者y的值发生变化的时候,f(x, y)的返回值才可能发生变化)。如果判别式函数需要访问那些可能会在调用时不确定,是变化的数据,那么用相同的参数在不同的时刻调用该函数就有可能会得到不同的结果,从而影响operator()的返回值。
因为判别式函数所能访问的数据应该仅局限于参数及常量,所以,判别式函数类中的operator()通常应该是const的
参考
《Effective STL》
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出