c++ for_each 引用调用

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++的东西。

留言评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注