我知道历史上最好使用标准算法,例如for_each
而不是for
循环,因为它们更具可读性。但是我觉得使用c ++ 11时,常规for循环比使用相应回调函数的众多标准算法要简洁得多。
我认为这是错的吗?许多标准算法已经过时了吗?这些方法提供了哪些不同的好处?
答案 0 :(得分:3)
使用你的判断。
由于lambdas和更好的绑定表达式,许多算法在C ++ 11中变得更容易使用,这使得您可以以相对简洁的方式指定仿函数。但是,基于范围的for
循环也是完全合法的选择。
如果你需要的只是循环体中的一个或两个语句,那么一定要使用基于范围的循环。如果需要在对象集合上调用成员函数,可以使用for_each
和mem_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循环都高效。