C++ STL - 迭代序列中的所有内容

发布于 2024-08-06 01:43:09 字数 672 浏览 2 评论 0原文

我有一个序列,例如

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

╭ゆ眷念 2024-08-13 01:43:09

您可以使用标准库中的 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;
    }
}

You could use for_each from the standard library. You could pass a functor or a function to it. The solution I like is BOOST_FOREACH, which is just like foreach in other languages. C+0x is gonna have one btw.

For example:

#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;
    }
}
云胡 2024-08-13 01:43:09

不包括 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());

两者都要求您在其他地方指定循环的“主体”,要么作为函数,要么作为函子(一个重载 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);
});

最后,它还将引入基于范围的 for 循环:

for(Foo& arg : my_someVariable)
{
  blah(arg.x, arg.y);
  woop(arg.z);
}

因此,如果您可以访问支持 C++0x 子集的编译器,您可能可以使用最后一种形式或两种形式。否则,惯用的解决方案(不使用 Boost)是使用 for_each 就像前两个示例之一一样。

Not counting BOOST_FOREACH which AraK already suggested, you have the following two options in C++ today:

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());

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 to for_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.

std::for_each(someVariable.begin(), someVariable.end(), [](Foo& arg){
  blah(arg.x, arg.y);
  woop(arg.z);
});

Finally, it will also introduce a range-based for loop:

for(Foo& arg : my_someVariable)
{
  blah(arg.x, arg.y);
  woop(arg.z);
}

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_eachlike in one of the two first examples.

望喜 2024-08-13 01:43:09

顺便说一下,MSVS 2008 有一个“foreach”C++ 关键字。查看如何:使用 foreach 迭代 STL 集合< /a>.

int main() {
   int retval = 0;

   vector<int> col(3);
   col[0] = 10;
   col[1] = 20;
   col[2] = 30;

   for each( const int& c in col )
      retval += c;

   cout << "retval: " << retval << endl;
}

By the way, MSVS 2008 has a "for each" C++ keyword. Look at How to: Iterate Over STL Collection with for each.

int main() {
   int retval = 0;

   vector<int> col(3);
   col[0] = 10;
   col[1] = 20;
   col[2] = 30;

   for each( const int& c in col )
      retval += c;

   cout << "retval: " << retval << endl;
}
分分钟 2024-08-13 01:43:09

更喜欢算法调用而不是手写循环

有三个原因:

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.

生来就爱笑 2024-08-13 01:43:09

更喜欢几乎所有其他算法而不是 for_each()

有两个原因:

  1. for_each 非常通用,它不会告诉您真正正在做什么,只是告诉您正在对序列中的所有项目执行某些操作。
  2. 更专业的算法通常会更简单、更直接

考虑一下之前回复中的一个例子:

void print(int v)
{
    std::cout << v << std::endl;
}
// ...
std::for_each(array.begin(), array.end(), print); // using STL

使用 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:

  1. for_each is extremely general, telling you nothing about what's really being done, just that you're doing something to all the items in a sequence.
  2. A more specialized algorithm will often be simpler and more direct

Consider, an example from an earlier reply:

void print(int v)
{
    std::cout << v << std::endl;
}
// ...
std::for_each(array.begin(), array.end(), print); // using STL

Using std::copy instead, that whole thing turns into:

std::copy(array.begin(), array.end(), std::ostream_iterator(std::cout, "\n"));

隔岸观火 2024-08-13 01:43:09
"struct functor {
  void operator()(Foo& arg){
    blah(arg.x, arg.y);
    woop(arg.z);
  }
};

std::for_each(someVariable.begin(), someVariable.end(), functor());"

我认为对于一个简单的问题来说,这样的方法通常是不必要的巴洛克式的。

do i=1,N
 call blah( X(i),Y(i) )
 call woop( Z(i) )
end do

非常清楚,即使它已经有 40 岁了(显然不是 C++)。

如果容器始终是一个向量(STL 名称),那么我认为索引没有任何问题,将该索引称为整数也没有问题。

在实践中,通常需要同时迭代多个相同大小的容器,并从每个容器中剥离一个数据,并对其中的大量容器执行某些操作。特别是在这种情况下,为什么不使用索引呢?

至于上面 SSS 的第 #2 点和第 #3 点,我想说对于复杂的情况可能如此,但通常迭代 1...N 通常与其他任何事情一样简单明了。

如果您必须在白板上解释算法,使用或不使用“i”您是否可以更快地完成?我认为如果你的物质空间解释通过索引更清晰,那么可以在代码空间中使用它。

把强大的 C++ 火力留给硬目标。

"struct functor {
  void operator()(Foo& arg){
    blah(arg.x, arg.y);
    woop(arg.z);
  }
};

std::for_each(someVariable.begin(), someVariable.end(), functor());"

I think approaches like these are often needlessly baroque for a simple problem.

do i=1,N
 call blah( X(i),Y(i) )
 call woop( Z(i) )
end do

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文