使用for_each和range-for有什么好处?

时间:2014-11-14 14:20:00

标签: c++ algorithm c++11

我知道历史上最好使用标准算法,例如for_each而不是for循环,因为它们更具可读性。但是我觉得使用c ++ 11时,常规for循环比使用相应回调函数的众多标准算法要简洁得多。

我认为这是错的吗?许多标准算法已经过时了吗?这些方法提供了哪些不同的好处?

3 个答案:

答案 0 :(得分:3)

使用你的判断。

由于lambdas和更好的绑定表达式,许多算法在C ++ 11中变得更容易使用,这使得您可以以相对简洁的方式指定仿函数。但是,基于范围的for循环也是完全合法的选择。

如果你需要的只是循环体中的一个或两个语句,那么一定要使用基于范围的循环。如果需要在对象集合上调用成员函数,可以使用for_eachmem_fn。如果绑定表达式看起来足够清楚,请使用它。但无论你做什么,如果你发现自己将太多的逻辑塞进一个地方,可以考虑重构并为较小的工作部分提供可读的名称。

C ++为您提供了许多工具,并且存在一个工具并不意味着另一个工具无用。大型工具带,就像C ++一样,面向经验丰富的用户,经验将让您选择合适的工具来完成正确的工作。

答案 1 :(得分:1)

这将是一个相当主观的话题,但是值得我同意的是。我认为使用语言结构比使用库结构要好得多,特别是当语言结构简洁易读时。 (对于for_each在c ++ 11之前的可读性,肯定有一个论点)

答案 2 :(得分:1)

就可读性而言,现在使用基于范围的for可能比使用std::for_each更好。不过,这不一定意味着for_each已过时。

考虑以下代码:

auto myVals = getManyValsInAContainer();

for (auto& val : myVals)
{
    doStuff(val);
}

与不那么可读的代码具有相同的作用:

auto myVals = getManyValsInAContainer();

for (auto it = myVals.begin(), end = myVals.end(); it != end; ++it)
{
    doStuff(*it);
}

现在,假设您的容器是std::deque,这意味着您的值位于连续内存的大块中,并带有一些指针来跟踪这些块的位置。对于知道实现的人来说,遍历该容器的所有元素很容易:它只需要一个双循环即可遍历 each 块的 each 元素。

但是基于范围的呢?它依靠operator++()从一个元素移到另一个元素。每次operator++()都必须检查下一个元素是否在同一块中,或者是否需要进行下一个块。这些调用彼此完全独立,因此无法提高效率。

(注意:请勿尝试手动执行操作:您需要为此访问容器的私有部分,即使您拥有它,想出的任何方法也只能用于STL的某些实现但其他人除外)

那么std::for_each有什么不同吗?好吧,一方面,它是一个功能模板,所以可以专门化。它也是STL的一部分,这意味着实施它的人员确切知道std::deque(或您使用的任何其他STL容器)的实现方式,并且他们可以使std::for_each成为以下方面的朋友容器类(或执行其需要做的其他事情)来高效地完成工作,而不是依赖多次调用operator++()

因此,您的答案是:std::for_each并不是过时的。可读性只是它要做的事情之一,但是当遍历STL容器时,可读性仍然比任何for循环都高效。