for_each,允许对区间内的元素进行修改,当然transform也可以实现相同的操作,只是transform效率较低,因为transform是通过拷贝函数返回值实现。当然C++11之后for_each变得不再重要,因为range-based for更加直观简单。
接下来我们看一下for_each的实现:
template<class _InIt,
class _Fn> inline
_Fn for_each(_InIt _First, _InIt _Last, _Fn _Func)
{ // perform function for each element [_First, _Last)
_DEBUG_RANGE(_First, _Last);
auto _UFirst = _Unchecked(_First);
const auto _ULast = _Unchecked(_Last);
for (; _UFirst != _ULast; ++_UFirst)
{
_Func(*_UFirst);
}
return (_Func);
}
通过源码可以清晰的看出for_each有三个参数,前两个参数用来确定一个区间,第三个参数则是操作方式,lambda,函数对象或者普通函数都可以充当其第三个参数,看下面这个例子:
class AddValue
{
private:
int theValue;
public:
AddValue (const int& v) : theValue(v)
{
}
void operator() (int& elem) const
{
elem += theValue;
}
};
void main()
{
void print(int n)
{
std::cout<<n;
}
...
std::vector<int>v1;
//lambda
for_each(v1.begin(),v1.end(),[]()
{
...
});
for_each(v1.begin(),v1.end(),print);//普通函数
for_each (v1.begin(), v1.end(), AddValue(10));//函数对象
}
for_each()有一个特殊的性质,那就是它能够返回其操作,利用这一特性,我们可以处理“置于该操作中的结果”直接看下面这个例子:
class MeanValue {
private:
long num;
long sum;
public:
MeanValue() : num(0), sum(0) {
}
void operator() (int elem) {
num++; // increment count
sum += elem; // add value
}
operator double() {
return static_cast<double>(sum) / static_cast<double>(num);
}
};
int main()
{
std::vector<int>v1{1,2,3,4,5,6,7,8};
double db = std::for_each(v1.begin(), v1.end(), MeanValue());
std::cout << db;
return 0;
}
输出结果:4.5
上面这个例子中有一点值得说一下:
double db = std::for_each(v1.begin(), v1.end(), MeanValue());通过观看源码,我们知道for_each的返回值是其第三个参数。而我们的第三个参数明明是一个class,为什么我们可以赋值给一个double类型?
这里我们就要注意了,在MeanValue类中我们有一个特殊的重载,operator double(){...} ,这个重载就是为了提供该类隐式转换为double的方法,所以我们可以将该类隐式转换为double类型。