繁体   English   中英

用C ++的std :: for_each函数

[英]Functor with std::for_each in C++

这是我从http://www.catonmat.net/blog/on-functors/复制的函子代码。

#include <algorithm>
#include <iostream>
#include <list>

class EvenOddFunctor {
    int even_;
    int odd_;
public:
    EvenOddFunctor() : even_(0), odd_(0) {}
    void operator()(int x) {
        if (x%2 == 0) even_ += x;
        else odd_ += x;
    }
    int even_sum() const { return even_; }
    int odd_sum() const { return odd_; }
};

int main() {
    EvenOddFunctor evenodd;

    int my_list[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    // ??? why assign 
    evenodd = std::for_each(my_list,
                  my_list+sizeof(my_list)/sizeof(my_list[0]),
                  evenodd); // ???

    std::cout << "Sum of evens: " << evenodd.even_sum() << "\n";
    std::cout << "Sum of odds: " << evenodd.odd_sum() << std::endl;

    // output:
    // Sum of evens: 30
    // Sum of odds: 25
}

为什么我们需要在操作之后像evenodd = std::for_each(my_list,一样)将值分配回evanodd对象?我认为随着从std :: for_each更新了evenodd对象,我不需要赋值操作,但没有分配,结果显示为0。

std::for_each按值接受函子,这意味着它将修改本地副本。 作业会获取该本地副本,因此您实际上可以看到修改后的版本。

这很重要,因为您的函子具有您感兴趣的可变状态,尤其是evenodd.even_sumevenodd.odd_sum

让我们做一些实验。

首先,尝试不分配它,看看会发生什么。 尝试之后,如果您发现了问题,则无需进一步阅读,因此可以停止。

如果您无法解决问题,请进行第二个实验,并如下更改main()的相关部分:

const EvenOddFunctor evenodd_orig;

int my_list[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// ??? why assign
auto evenodd = std::for_each(my_list,
              my_list+sizeof(my_list)/sizeof(my_list[0]),
              evenodd_orig); // ???

这里的关键部分是您要将一个常量对象传递给std::for_each 这将编译,但是如果std::for_each以您认为的方式工作,则不应编译。

毕竟, operator() 不是常量方法,因此,如果std::for_each获得const引用,它就不能调用可变的operator()方法。

那是因为实际上发生的是std::for_each对传递给它的函子进行内部复制。 它通过值而不是通过引用获取函子参数,并且函子最终修改了其内部状态。

这就是为什么std::for_each返回函子对象的原因,这就是为什么您需要存储它的原因,因为传递给std::for_each的原始对象尚未修改!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM