for_each算法定义在<algorithm>头文件中,需要在使用该算法时include<algorithm>头文件。
std::for_each的功能是对区间[first,last)上的每一个元素调用function,第三个参数可以全局函数,函数对象,lambda表达式,并且是一个一元函数。
其定义如下,各编译器实现可能不同:
template< class InputIt, class UnaryFunction >
UnaryFunction for_each( InputIt first, InputIt last, UnaryFunction function );
功能:对区间[first, last)中的每一个元素调用function 。
参数first,last:指定该算法操作的区间[first, last)。
参数function : 一元函数,即UnaryFunction ,可以是全局函数(函数指针),函数对象,lambda等,默认按值传递。
返回值:返回function 的一个副本,function的任何返回值都将被忽略.
复杂度:log(n), 与区间中的元素个数呈线性变换。
注意:第三个参数function默认是按值传递的。也就是说,std::for_each内部操作的是function的副本,另外,返回值也是按值返回的。当然,你也可以打破这种限制(参考:Effective STL 的38条款)
尽管我们可以使用完全for来实现相同的目的,但是std::for_each可以节省时间和代码数量,也减少了一些错误的机会。
示例1:打印纯数组(C数组)中的元素。
//static全局函数
static void printElement(int &item)
{
std::cout << item << " ";
}
//函数对象类
class Printer
{
public:
void operator()(int& item){std::cout << item<<" ";}
};
int main(int argc, char *argv[])
{
int plainArray[] {2,6,3,1,9,8,10,5,4,0};
//第三个参数为static全局函数
std::for_each(std::begin(plainArray), std::end(plainArray), printElement);
std::cout << std::endl;
//第三个参数为lambda
std::for_each(std::begin(plainArray), std::end(plainArray), [](int &Item){std::cout << Item << " ";});
std::cout << std::endl;
//第三个参数为函数对象
std::for_each(std::begin(plainArray), std::end(plainArray), Printer());
std::cout << std::endl;
return 0;
}
示例2:std::for_each的返回值。
有时候,我们可以充分利用std::for_each的返回值完成一些事情。比如,计算容器/数组元素的sum。
我们可以使用std::for_each和函数对象来完成这个功能。
class Sum{
public:
Sum():sum{0}
{
}
void operator()(const int& item)
{
sum +=item;
}
int getSum(){
return sum;
}
private:
int sum;
};
int main(int argc, char *argv[])
{
std::vector<int> nums{0,1,2,3,4,5,6,7,8,9};
Sum elements = std::for_each(nums.begin(), nums.end(),Sum());
std::cout << elements.getSum() << std::endl;
return 0;
}
示例3:验证第三个参数默认是按值传递的。
class Sum{
public:
Sum():sum{0}
{
}
void operator()(const int& item)
{
sum +=item;
}
int getSum(){
return sum;
}
private:
int sum;
};
int main(int argc, char *argv[])
{
std::vector<int> nums{0,1,2,3,4,5,6,7,8,9};
Sum Temp;
std::cout << "Begin, Temp'sum = "<< Temp.getSum() << std::endl;
std::for_each(nums.begin(), nums.end(),Temp);
std::cout << "After, Temp'sum = "<< Temp.getSum() << std::endl;
return 0;
}
输出:
Begin, Temp’ sum = 0
After, Temp’ sum = 0
那么,如果我们真的需要第三个参数按引用传递,我们可以这个做:
int main(int argc, char *argv[])
{
std::vector<int> nums{0,1,2,3,4,5,6,7,8,9};
Sum Temp;
std::cout << "Begin, Temp'sum = "<< Temp.getSum() << std::endl;
//显示指定std::for_each的第二个模板参数按引用传递,此时返回值和第三个参数都是按引用传递。
std::for_each<std::vector<int>::iterator, Sum&>(nums.begin(), nums.end(),Temp);
std::cout << "After, Temp'sum = "<< Temp.getSum() << std::endl;
return 0;
}
输出:
Begin, Temp’sum = 0
After, Temp’sum = 45
虽然按引用传递可能会达成某种目的,但是不推荐这么做。