我有一个序列,例如
std::vector< Foo > someVariable;
Run Code Online (Sandbox Code Playgroud)
我想要一个循环遍历其中的所有内容.
我能做到这一点:
for (int i=0;i<someVariable.size();i++) {
blah(someVariable[i].x,someVariable[i].y);
woop(someVariable[i].z);
}
Run Code Online (Sandbox Code Playgroud)
或者我可以这样做:
for (std::vector< Foo >::iterator i=someVariable.begin(); i!=someVariable.end(); i++) {
blah(i->x,i->y);
woop(i->z);
}
Run Code Online (Sandbox Code Playgroud)
这些似乎都涉及相当多的重复/过度打字.在理想的语言中,我希望能够做到这样的事情:
for (i in someVariable) {
blah(i->x,i->y);
woop(i->z);
}
Run Code Online (Sandbox Code Playgroud)
似乎迭代顺序中的所有内容将是一个非常常见的操作.有没有办法做到这一点,代码不是它应该的两倍长?
Ara*_*raK 12
您可以使用for_each标准库.您可以将仿函数或函数传递给它.我喜欢的解决方案BOOST_FOREACH就是和foreach其他语言一样.C + 0x会有一个顺便说一句.
例如:
#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/foreach.hpp>
#define foreach BOOST_FOREACH
void print(int v)
{
std::cout << v << std::endl;
}
int main()
{
std::vector<int> array;
for(int i = 0; i < 100; ++i)
{
array.push_back(i);
}
std::for_each(array.begin(), array.end(), print); // using STL
foreach(int v, array) // using Boost
{
std::cout << v << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
不计算AraK已经建议的BOOST_FOREACH,你今天在C++中有以下两个选项:
void function(Foo& arg){
blah(arg.x, arg.y);
woop(arg.z);
}
std::for_each(someVariable.begin(), someVariable.end(), function);
struct functor {
void operator()(Foo& arg){
blah(arg.x, arg.y);
woop(arg.z);
}
};
std::for_each(someVariable.begin(), someVariable.end(), functor());
Run Code Online (Sandbox Code Playgroud)
两者都要求您在其他地方指定循环的"主体",可以是函数,也可以是函数(重载的类operator()).这可能是一件好事(如果你需要在多个循环中做同样的事情,你只需要定义一次函数),但它也可能有点乏味.函数版本的效率可能稍低,因为编译器通常无法内联函数调用.(函数指针作为第三个参数传递,编译器必须进行更详细的分析以确定它指向的函数)
仿函数版本基本上是零开销.因为functor传递了一个类型的对象for_each,编译器确切地知道要调用哪个函数:functor::operator()所以它可以简单地内联并且与原始循环一样有效.
C++ 0x将引入lambda表达式,使第三种形式成为可能.
std::for_each(someVariable.begin(), someVariable.end(), [](Foo& arg){
blah(arg.x, arg.y);
woop(arg.z);
});
Run Code Online (Sandbox Code Playgroud)
最后,它还将介绍一个基于范围的for循环:
for(Foo& arg : my_someVariable)
{
blah(arg.x, arg.y);
woop(arg.z);
}
Run Code Online (Sandbox Code Playgroud)
因此,如果您可以访问支持C++ 0x子集的编译器,那么您可以使用最后一个或两个表单.否则,惯用解决方案(不使用Boost)for_each就像在前两个例子中使用一样.