C++ STL - 遍历序列中的所有内容

Ang*_*gus 5 c++ stl

我有一个序列,例如

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)


jal*_*alf 5

不计算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就像在前两个例子中使用一样.