C++中的 for_each
函数是for循环的一种替代方案。for_each
位于算法库中,调用的时候需要包含algorithm头文件。
for_each
的原型为:
template<class InputIt, class UnaryFunction> UnaryFunction for_each( InputIt first, InputIt last, UnaryFunction f );
前两个参数为起止迭代器,第三个参数是一个一元函数。C++11标准已经实现了闭包,第三个参数可以使用闭包替代,无需额外再定义函数实体。
下面是 for_each
的一个简单应用:
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
std::vector<int> nums{3, 4, 2, 9, 15, 267};
std::cout < < "before: ";
for (auto n : nums) {
std::cout << n << " ";
}
std::cout << '/n';
std::for_each(nums.begin(), nums.end(), [](int &n){ n++; });
std::cout << "after: ";
for (auto n : nums) {
std::cout << n << " ";
}
return 0;
}
上述代码将输出:
before: 3 4 2 9 15 267 after: 4 5 3 10 16 268
可以看到for_each的使用还是非常方便的。需要说明的是第三个参数是函数,其接收值应当为 *InputIt
类型。上述案例中vector的元素是 int
类型,所以闭包的参数类型也应该是 int
类型。并且我们使用的是引用调用。
再来看一个复杂的例子:
std::map<std::string , CFoo*> _map;
// some codes
for_each (
_map.begin(),
_map.end(),
[](std::pair<std::string , CFoo*> value) {
value.second->run();
});
上述示例中,操作对象为map类型,匿名函数的接受对应改成了相应的 pair
类型。上述代码编译和运行都没有问题,结果也正确。但是如果有一个函数,需要接受引用参数,可能会引发问题:
for_each (
_map.begin(),
_map.end(),
[](std::pair<std::string , CFoo*>& value) {
value.second->setDefault();
});
setDefault
函数将_map对象里的值变成默认值,我们希望此操作是引用调用,对输入参数有影响。直接看上面的代码,应该没有问题,遗憾的是上述代码编译不能通过。编译器报了一堆错误,其中有个重要的就是说转换失败。
问题出在了对 map
的key的改变上,第三个函数接受的pair对象应当是保持key不变的,当时上面的叙述没有体现这一点。所以正确的做法是:
for_each (
_map.begin(),
_map.end(),
[](std::pair<const std::string, CFoo*>& value) {
value.second->setDefault();
});
需要把key声明为const类型,这样才能编译通过。
解决了一个坑,以后还需要多学习c++的东西。