C++ STL - 迭代序列中的所有内容
我有一个序列,例如
std::vector< Foo > someVariable;
,我想要一个循环遍历其中的所有内容。
我可以这样做:
for (int i=0;i<someVariable.size();i++) {
blah(someVariable[i].x,someVariable[i].y);
woop(someVariable[i].z);
}
或者我可以这样做:
for (std::vector< Foo >::iterator i=someVariable.begin(); i!=someVariable.end(); i++) {
blah(i->x,i->y);
woop(i->z);
}
这两者似乎都涉及相当多的重复/过多的打字。在理想的语言中,我希望能够做这样的事情:
for (i in someVariable) {
blah(i->x,i->y);
woop(i->z);
}
似乎迭代序列中的所有内容将是一个非常常见的操作。有没有一种方法可以做到这一点,其中代码的长度不是应有的两倍?
I have a sequence, e.g
std::vector< Foo > someVariable;
and I want a loop which iterates through everything in it.
I could do this:
for (int i=0;i<someVariable.size();i++) {
blah(someVariable[i].x,someVariable[i].y);
woop(someVariable[i].z);
}
or I could do this:
for (std::vector< Foo >::iterator i=someVariable.begin(); i!=someVariable.end(); i++) {
blah(i->x,i->y);
woop(i->z);
}
Both these seem to involve quite a bit of repetition / excessive typing. In an ideal language I'd like to be able to do something like this:
for (i in someVariable) {
blah(i->x,i->y);
woop(i->z);
}
It seems like iterating through everything in a sequence would be an incredibly common operation. Is there a way to do it in which the code isn't twice as long as it should have to be?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您可以使用标准库中的
for_each
。您可以向其传递函子或函数。我喜欢的解决方案是BOOST_FOREACH
,它就像其他语言中的foreach
一样。顺便说一句,C+0x 会有一个。例如:
You could use
for_each
from the standard library. You could pass a functor or a function to it. The solution I like isBOOST_FOREACH
, which is just likeforeach
in other languages. C+0x is gonna have one btw.For example:
不包括 AraK 已经建议的 BOOST_FOREACH ,现在 C++ 中有以下两个选项:
两者都要求您在其他地方指定循环的“主体”,要么作为函数,要么作为函子(一个重载
operator( 的类) )
)。这可能是一件好事(如果您需要在多个循环中执行相同的操作,则只需定义该函数一次),但它也可能有点乏味。函数版本的效率可能会稍低一些,因为编译器通常无法内联函数调用。 (函数指针作为第三个参数传递,编译器必须做一些更详细的分析才能确定它指向哪个函数)函子版本基本上是零开销。由于
functor
类型的对象被传递给for_each
,编译器确切地知道要调用哪个函数:functor::operator()
,等等它可以简单地内联,并且与原始循环一样高效。C++0x 将引入 lambda 表达式,从而使第三种形式成为可能。
最后,它还将引入基于范围的 for 循环:
因此,如果您可以访问支持 C++0x 子集的编译器,您可能可以使用最后一种形式或两种形式。否则,惯用的解决方案(不使用 Boost)是使用
for_each
就像前两个示例之一一样。Not counting BOOST_FOREACH which AraK already suggested, you have the following two options in C++ today:
Both require you to specify the "body" of the loop elsewhere, either as a function or as a functor (a class which overloads
operator()
). That might be a good thing (if you need to do the same thing in multiple loops, you only have to define the function once), but it can be a bit tedious too. The function version may be a bit less efficient, because the compiler is generally unable to inline the function call. (A function pointer is passed as the third argument, and the compiler has to do some more detailed analysis to determine which function it points to)The functor version is basically zero overhead. Because an object of type
functor
is passed tofor_each
, the compiler knows exactly which function to call:functor::operator()
, and so it can be trivially inlined and will be just as efficient as your original loop.C++0x will introduce lambda expressions which make a third form possible.
Finally, it will also introduce a range-based for loop:
So if you've got access to a compiler which supports subsets of C++0x, you might be able to use one or both of the last forms. Otherwise, the idiomatic solution (without using Boost) is to use
for_each
like in one of the two first examples.顺便说一下,MSVS 2008 有一个“foreach”C++ 关键字。查看如何:使用 foreach 迭代 STL 集合< /a>.
By the way, MSVS 2008 has a "for each" C++ keyword. Look at How to: Iterate Over STL Collection with for each.
更喜欢算法调用而不是手写循环
有三个原因:
1)效率:算法通常比程序员生成的循环更有效
2)正确性:
3) 可维护性:算法调用通常会产生更清晰、更多的代码
比相应的显式循环简单。
Prefer algorithm calls to hand-written loops
There are three reasons:
1) Efficiency: Algorithms are often more efficient than the loops programmers produce
2) Correctness: Writing loops is more subject to errors than is calling algorithms.
3) Maintainability: Algorithm calls often yield code that is clearer and more
straightforward than the corresponding explicit loops.
更喜欢几乎所有其他算法而不是 for_each()
有两个原因:
考虑一下之前回复中的一个例子:
使用 std::copy 代替,整个事情变成:
std::copy(array.begin(), array.end(), std::ostream_iterator(std::cout, "\n"));
Prefer almost every other algorithm to for_each()
There are two reasons:
Consider, an example from an earlier reply:
Using std::copy instead, that whole thing turns into:
std::copy(array.begin(), array.end(), std::ostream_iterator(std::cout, "\n"));
我认为对于一个简单的问题来说,这样的方法通常是不必要的巴洛克式的。
非常清楚,即使它已经有 40 岁了(显然不是 C++)。
如果容器始终是一个向量(STL 名称),那么我认为索引没有任何问题,将该索引称为整数也没有问题。
在实践中,通常需要同时迭代多个相同大小的容器,并从每个容器中剥离一个数据,并对其中的大量容器执行某些操作。特别是在这种情况下,为什么不使用索引呢?
至于上面 SSS 的第 #2 点和第 #3 点,我想说对于复杂的情况可能如此,但通常迭代 1...N 通常与其他任何事情一样简单明了。
如果您必须在白板上解释算法,使用或不使用“i”您是否可以更快地完成?我认为如果你的物质空间解释通过索引更清晰,那么可以在代码空间中使用它。
把强大的 C++ 火力留给硬目标。
I think approaches like these are often needlessly baroque for a simple problem.
is perfectly clear, even if it's 40 years old (and not C++, obviously).
If the container is always a vector (STL name), I see nothing wrong with an index and nothing wrong with calling that index an integer.
In practice, often one needs to iterate over multiple containers of the same size simultaneously and peel off a datum from each, and do something with the lot of them. In that situation, especially, why not use the index?
As far as SSS's points #2 and #3 above, I'd say it could be so for complex cases, but often iterating 1...N is often as simple and clear as anything else.
If you had to explain the algorithm on the whiteboard, could you do it faster with, or without, using 'i'? I think if your meatspace explanation is clearer with the index, use it in codespace.
Save the heavy C++ firepower for the hard targets.