3

根据这个问题的第一个答案,下面的仿函数在被传递给之后应该能够保留一个值foreach(我无法struct Accumulator在示例中编译,所以构建了一个类)。

class Accumulator
{
    public:
        Accumulator(): counter(0){}
        int counter;
        void operator()(const Card & c) { counter += i; }
};

示例用法(根据示例)

// Using a functor
Accumulator acc;
std::for_each(_cards.begin(), _cards.end(), acc);
// according to the example - acc.counter contains the sum of all
// elements of the deque 

std::cout << acc.counter << std::endl;

_cards被实现为std::deque<Card>. 不管_cards得到多长时间,完成acc.counter后为零for_each。但是,当我在调试器中逐步执行时,我可以看到计数器在递增,那么这与acc按值传递有关吗?

4

3 回答 3

6

这只是在这里被问到的

原因是(如您所料)std::for_each复制它的函子,并调用它。但是,它也会返回它,因此如上面链接的答案中所述,使用返回值for_each.

也就是说,您只需要使用std::accumulate

int counter = std::accumulate(_cards.begin(), _cards.end(), 0);

函子for_each在这里不正确。


对于您的使用(计算一些,忽略其他),您可能需要提供自己的仿函数并使用count_if

// unary_function lives in <functional>
struct is_face_up : std::unary_function<const Card&, const bool>
{
    const bool operator()(const card& pC) const
    {
        return pC.isFaceUp(); // obviously I'm guessing
    }
};

int faceUp = std::count_if(_cards.begin(), _cards.end(), is_face_up());
int faceDown = 52 - faceUp;

并且使用 C++0x lambda 来获得乐趣(只是因为):

int faceUp = std::count_if(_cards.begin(), _cards.end(),
                            [](const Card& pC){ return pC.isFaceUp(); });

好多了。

于 2010-01-20T14:59:57.190 回答
3

是的,它肯定与 acc 按值传递有关。

修改你的累加器如下:

class Accumulator
{
    public:
        Accumulator(): counter(new int(0)){}
        boost::shared_ptr<int> counter;
        void operator()(int i) { *counter += i; }

        int value() { return *counter; }
};
于 2010-01-20T14:53:51.950 回答
3

这是因为 std::for_each() 在内部制作了仿函数的副本(因为它可以传递临时对象)。所以在内部它确实对副本而不是您提供的对象进行求和。

好消息是 std::for_each() 作为结果返回函子的副本,因此您可以从那里访问它。

注意:您可以使用其他标准算法。像 std::accumulate() 一样。
但是假设这只是一个简化的示例,并且您需要 for_each() 比示例稍微复杂一些,有一些技术可以让您访问累加器对象。

#include <iostream>
#include <algorithm>
#include <vector>

class Card{ public: int i;};
class Accumulator
{
    public:
        Accumulator(): counter(0){}
        int counter;
        void operator()(const Card & c) { counter += c.i; }
};


int main()
{
    std::vector<Card>   cards;

    Accumulator a = std::for_each(cards.begin(), cards.end(), Accumulator());

    std::cout << a.counter << std::endl;

}

或者,您可以更改您的累加器以增加在当前范围内使用的引用。

#include <iostream>
#include <algorithm>
#include <vector>

class Card{ public: int i;};
class Accumulator
{
        int&  counter;
    public:
        // Pass a reference to constructor.
        // Copy construction will pass this correctly into the internal object used by for_each
        Accumulator(int& counterRef): counter(counterRef){}
        void operator()(const Card & c) { counter += c.i; }
};


int main()
{
    std::vector<Card>   cards;

    int counter = 0;  // Count stored here.

    std::for_each(cards.begin(), cards.end(), Accumulator(counter));

    std::cout << counter << std::endl;

}
于 2010-01-20T15:27:58.233 回答