有没有办法从我传递给foreach的函数中获得返回值。
对于前: 我有,
void myfunction (int i)
{
cout << " " << i;
}
vector<int> myvector;
myvector.push_back(10);
for_each (myvector.begin(), myvector.end(), myfunction);
让我们说,我想使用一些规则计算向量中的元素数量,我想从myFunction获得返回值,这可能吗?
答案 0 :(得分:13)
有一个特殊目的std::count
(值的计数出现)和std::count_if
(谓词返回true时计数)。不要将std::for_each
滥用于不适合的内容。
答案 1 :(得分:9)
for_each
将返回您传递的仿函数的副本。这意味着你可以这样做:
template <typename T>
class has_value
{
has_value(const T& pValue) : mValue(pValue), mFlag(false) {}
void operator()(const T& pX)
{
if (pX == mValue)
mFlag = true;
}
operator bool(void) const { return mFlag; }
private:
T mValue;
bool mFlag;
};
bool has_seven = std::for_each(myvector.begin(), myvector.end(), has_value<int>(7));
答案 2 :(得分:5)
没有。但是你可以使myfunction
成为一个仿函数,将指针传递给某个内存,并通过该指针存储你的返回值。
struct MyFunctor {
int *count;
MyFunctor(int *count_) : count(count_) { }
void operator()(int n) {
if (n > 5) (*count)++;
}
};
int main() {
vector<int> vec;
for (int i=0; i<10; i++) vec.push_back(i);
int count = 0;
for_each(vec.begin(), vec.end(), Myfunctor(&count));
printf("%d\n", count);
return 0;
}
编辑:正如评论所指出的那样,我的第一个例子会失败,因为for_each
会复制MyFunctor
,所以我们不能拥有从原始对象中检索返回值。我已经修改了原来的方法;但你真的应该看看更加优雅的GMan解决方案。我不确定可移植性,但它确实适用于我的gcc
(4.4.2)。正如其他人提到的那样,尽可能使用<algorithm>
提供的内容。
答案 3 :(得分:3)
如果你想要强大的foreach,那就是BOOST_FOREACH makro。此外,boost主要是头库,因此您只能将boost_foreach.hpp(afair)包含在项目中。例如:
BOOST_FOREACH( int & i , my_vector )
{
i = 0;
}
My_vector可以是vector<int>
或int[]
或任何其他类型的迭代器。
答案 4 :(得分:2)
这不是functors的用途吗?
答案 5 :(得分:1)
std::for_each
并非专为此而设计。使用std::count
计算等于某个值的元素数,或std::count_if
计算满足某些谓词的元素:
std::vector<SomeType> vec;
std::count(vec.begin(), vec.end(), SomeType(9));
/*or */
bool myfunc(const SomeType& v)
{
return v == 9;
}
std::count_if(vec.begin(), vec.end(), f);
如果您只想将容器的内容复制到像std::cout
这样的ostream对象,请改用std :: copy:
std::vector<SomeType> vec;
...
std::copy(vec.begin(), vec.end(), \
std::ostream_iterator<SomeType>(std::cout," "));
如果需要每次调用函数的返回值,请使用std::transform
:
std::vector<SomeType> src;
std::vector<SomeType> result;
int myfunc(int val)
{
...
}
std::transform(src.begin(), src.end() \
result.begin(), myfunc);
std::transform
也被重载,因此它适用于二进制函数和一元函数。
答案 6 :(得分:1)
好吧,我担心你在选择计数问题时选择了你的例子......
问题在于for_each
非常通用,并且针对特定实施存在更具体的算法(count
,accumulate
,transform
,...)
让我们再举一个例子:for_each
通常用于对它所对待的对象应用变异操作。它不会阻止您在执行此操作时收集统计信息。
我们必须小心,虽然for_each
确实返回Predicate
对象,但无法保证此对象在范围内的每个项目上都使用。该实现可以自由地复制谓词并在部分范围内使用副本...所以你最终返回的副本可能是不受欢迎的。
class Predicate
{
public:
Predicate(size_t& errors) : m_errors(errors) {}
void operator()(MyObject& o)
{
try { /* complicated */ } catch(unfit&) { ++m_errors; }
}
private:
size_t& m_errors;
};
std::vector<MyObject> myVec;
// fill myVec
size_t errors = 0;
std::for_each(myVec.begin(), myVec.end(), Predicate(errors));
这里的技巧是原始谓词的所有副本都将指向相同的size_t
变量,因此该变量已被正确更新。
答案 7 :(得分:1)
你可以改编std::for_each
来做这件事,就像GMan所说的那样。
但更好的解决方案是使用正确的算法。
您应该能够使用std::count
或std::count_if
,或者std::accumulate
。
这些允许您返回一个结果来处理整个序列。
或者std::transform
允许您返回序列中每个元素的结果,创建一个包含结果的新输出序列。
答案 8 :(得分:0)
看看<algorithm>。
我认为std::count_if是您正在寻找的。 p>
答案 9 :(得分:0)
这是可行的:
int main()
{
std::vector<int> v;
for (int i = 1; i <= 10; i++)
v.push_back(i);
int hits = 0;
CountEven evens(&hits);
std::for_each(v.begin(), v.end(), evens);
std::cout << "hits = " << hits << std::endl;
return 0;
}
但请看一下CountEvens
的讨厌的实现:
class CountEven {
public:
CountEven(int *hits) : hits(hits) {}
CountEven(const CountEven &rhs) : hits(rhs.hits) {}
void operator() (int n) { if (n % 2 == 0) ++*hits; }
private:
int *hits;
};
请注意,复制构造函数会导致多个实例共享同一个指针。