这些 问题让我对每个宏的 Boost 和 Qt 的用途感到好奇。
我使用过 Qt 并发现宏一直都能很好地满足我的需求,但从未广泛测试过它的性能。我以前没有使用过 Boost 的产品。
我想知道什么时候是使用 Qt 和 Boost over 提供的替代品的好时机std::for_each
?
注意:措辞已经从原来的改变,使问题更客观。
的目的和功能std::for_each
与宏BOOST_FOREACH
和Q_FOREACH
.
std::for_each
首先是一个函数调用。它是一种算法。您调用它,提供一对迭代器。在迭代器范围的每个成员上,它将使用从相关迭代器中获取的值调用给定函数。
std::for_each
从概念上讲,它的目的实际上是与已经存在的更具体的算法相匹配。使用 , 等算法count
,copy
让一个简单地为每个元素执行任意代码的算法是有意义的。
BOOST_FOREACH
和Q_FOREACH
是等效的结构(我将统称为FOREACH
),但行为与std::for_each
.
FOREACH
首先是一个for 循环。现在,这听起来可能没什么不同,但想想看。你不能从内部调用continue
和。可以很容易地模拟(尽管这也意味着您不能从发出调用的函数返回)。但是如果你想停下来,就没有办法摆脱循环。同样,您也不能跳出循环。在任何一种情况下,你能做的最好的事情就是抛出一个异常,那就是使用异常来进行流控制(即:不是一个好主意)。break
std::for_each
continue
return
std::for_each
std::for_each
goto
for_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
循环。
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);
}
用法:您认为哪个最易读,并避免不必要的代码重复。
性能:每一个都是宏或模板函数,并且对编译器完全可见,差异应该只存在于调试版本中。