泛型算法之std::for_each

 for_each,允许对区间内的元素进行修改,当然transform也可以实现相同的操作,只是transform效率较低,因为transform是通过拷贝函数返回值实现。当然C++11之后for_each变得不再重要,因为range-based for更加直观简单。

接下来我们看一下for_each的实现:

template 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<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(sum) / static_cast(num);
	}
};


int main()
{
    std::vectorv1{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类型。

你可能感兴趣的:(STL算法)