2

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

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

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

注意:措辞已经从原来的改变,使问题更客观。

4

3 回答 3

5

的目的和功能std::for_each与宏BOOST_FOREACHQ_FOREACH.

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

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

BOOST_FOREACHQ_FOREACH是等效的结构(我将统称为FOREACH),但行为std::for_each.

FOREACH首先是一个for 循环。现在,这听起来可能没什么不同,但想想看。你不能从内部调用continue和。可以很容易地模拟(尽管这也意味着您不能从发出调用的函数返回)。但是如果你想停下来,就没有办法摆脱循环。同样,您也不能跳出循环。在任何一种情况下,你能做的最好的事情就是抛出一个异常,那就是使用异常来进行流控制(即:不是一个好主意)。breakstd::for_eachcontinuereturnstd::for_eachstd::for_eachgotofor_each

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

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

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

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

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

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

于 2012-05-10T21:31:51.923 回答
1

std::for_each是 C++ 标准的一部分,并且自 1998 年以来一直是(至少)。因此,任何(不那么)现代 C++ 都是不兼容的,因此如果它不提供for_each. 我每天使用的所有编译器都支持它。

您提到的两个库都存在于 C++ 语言本身之外。 for_each是唯一一个保证出现在符合标准的编译器中的。

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

于 2012-05-09T22:19:15.523 回答
1

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

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

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

于 2012-05-10T21:20:56.903 回答