根据this问题的第一个答案,下面的仿函数应该能够在传递给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
有关?
答案 0 :(得分:6)
这只是asked here。
原因是(正如您猜测的那样)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(); });
好多了。
答案 1 :(得分: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; }
};
答案 2 :(得分: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;
}
或者,您可以更改Accumalator以增加当前范围内使用的引用。
#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;
}