正确使用C++ 'for each'选项

Proper use of C++ 'for each' options

本文关键字:for each 选项 C++      更新时间:2023-10-16

这些问题让我对每个宏的 Boost 和 Qt 的目的感到好奇。

使用过Qt,发现宏一直可以很好地满足我的需求,但从未广泛测试过它的性能。我以前没有使用过Boost的产品。

我想知道的是什么时候是使用Qt和std::for_each Boost提供的替代方案的好时机?

注意:措辞已从原来更改,以使问题更加客观。

std::for_each的目的和功能与宏BOOST_FOREACHQ_FOREACH的目的和功能有很大不同。

std::for_each首先是一个函数调用。它是一种算法。你调用它,提供一对迭代器。在迭代器范围的每个成员上,它将使用从相关迭代器获取的值调用给定函数。

从概念上讲,std::for_each的目的实际上是与已经存在的更具体的算法相匹配。对于像countcopy等算法,拥有一个为每个元素简单地执行任意代码的算法是有意义的。

BOOST_FOREACHQ_FOREACH 是等效的结构(我统称为 FOREACH (,但行为std::for_each不同。

FOREACH首先是一个 for 循环。现在,这听起来可能没有那么不同,但想想看。您不能从 std::for_each 内部调用continuebreakcontinue 可以使用 return 轻松模拟(尽管这也意味着您无法从发出 std::for_each 调用的函数返回(。但是如果你想停下来,就没有办法从std::for_each循环中逃脱。同样,您也不能goto脱离for_each循环。在任何一种情况下,您能做的最好的事情就是抛出异常,这是使用异常进行流控制(即:不是一个好主意(。

当你使用std::for_each时,你必须提供一些可调用的函数。这可以是函数指针或函数对象。因此,您的代码在某种程度上是非本地化的。如果您在每次迭代中执行的操作是一个复杂的多行函数,这很好。但是,如果每次迭代的逻辑都非常简单,那么代码的可读性就会降低一点。

FOREACH执行本地代码块。所以代码就在那里;您不必跟踪函数即可查看每次迭代中发生的情况。

此外,调用函数意味着必须编写该函数。如果需要跟踪状态,现在需要一个函子,这需要更多的代码来编写。

C++11 使 lambda 函数std::for_each更具吸引力。这消除了代码局部性问题:源代码就在那里。由于 lambda 可以捕获东西,它几乎可以像常规for循环一样工作。好吧,除了没有break功能,但这通常是可以避免的。

当然,C++11 也使其有效地过时(连同 FOREACH (基于范围的for循环。但是,由于与 C++11 的一致性级别不同,因此在某些环境中,您有 lambda 但没有基于范围的for .

你应该使用什么取决于你。 FOREACH很好,如果你已经在使用Boost和/或Qt,那就随意吧。但我不会突然开始使用这些只是为了FOREACH.就个人而言,由于代码局部性问题,除非您也使用 lambda 或其他东西,否则我不会使用 std::for_each。只需使用for循环。

std::for_each是C++标准的一部分,至少自1998年以来一直如此。 因此,任何(不那么(现代C++都是不合规的,因此如果它不提供for_each,就会被破坏。 我每天使用的所有编译器都支持它。

你提到的两个库都存在于C++语言本身之外。 for_each是唯一保证存在于一致性编译器中的编译器。

至于利弊,我留给你决定。 如果可以选择,我会选择标准保证的东西,而不是标准保证的东西。

std::for_each 需要函子lambda函数指针才能执行。使用它,如果在代码中的多个位置循环相同的方法,则可以避免大量样板。

 void hello(int i){
      printf("World %d n",i);
 }
 std::vector<int> vals;
 vals.push_back(1);
 vals.push_back(2);
 std::for_each(vals.begin(),vals.end(),hello);

BOOST_FOREACH 和 Q_FOREACH 用于隐藏 C++ 迭代器的样板,它们替换了正常的 for 语句并在循环体上循环。

  for(vector<int>::iterator iter = vals.begin();iter != vals.end();++iter)
  {
      hello(*iter);
  }
  Q_FOREACH(int val, vals){
      hello(val);
  }

用法:您认为最易读并避免不必要的代码重复的用法。

性能:其中每一个都是宏或模板函数,对编译器完全可见,差异应该只存在于调试版本中。