使用 for_each 与范围有什么好处
What are the benefits of using for_each vs. range-for?
我知道从历史上看,最好使用标准算法(如for_each
)而不是for
循环,因为它们更具可读性。但我只是觉得使用 c++11 的常规 for 循环比具有相应回调函子的众多标准算法要简洁得多。
我这样想错了吗?许多标准算法是否已经过时?这些方法提供了哪些不同的好处?
使用你的判断。
由于 lambda 和更好的绑定表达式,许多算法在 C++11 中变得更容易使用,这允许您以相对简洁的方式指定函子。但是,基于范围的for
循环也是一个完全合法的选择。
如果您只需要循环体中的一个或两个语句,那么一定要使用基于范围的循环。如果需要在对象集合上调用成员函数,可以使用 for_each
和 mem_fn
。如果绑定表达式看起来足够清晰,请使用它。但无论你做什么,如果你发现自己在一个地方塞进了太多的逻辑,请考虑重构并为较小的工作组件提供可读的名称。
C++为您提供了许多工具,一种工具的存在并不意味着另一种工具毫无用处。大型工具带,就像C++一样,针对有经验的用户,经验可以让您为正确的工作选择正确的工具。
在可读性方面,使用基于范围的 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
,这意味着您的值位于连续内存的大块中,并带有一些指针来跟踪这些块的位置。对于了解实现的人来说,遍历该容器的所有元素很容易:它只需要一个双循环来遍历每个块的每个元素。
但是基于范围的呢?它依赖于operator++()
从一个元素移动到下一个元素。每次这样做时,operator++()
都必须检查下一个元素是否在同一个块中,或者是否需要继续下一个块。这些调用彼此完全独立,因此无法提高效率。
(注意:不要尝试手动做事:为此,您需要访问容器的私有部分,即使您拥有它,无论您想出什么都仅适用于 STL 的某些实现,而不适用于其他实现)
那么在std::for_each
方面有什么不同吗?嗯,一方面它是一个函数模板,所以它可以是专门的。它也是 STL 的一部分,这意味着实现它的人确切地知道std::deque
(或你正在使用的任何其他 STL 容器)是如何实现的,并且他们可以std::for_each
成为容器类的朋友(或做他们需要做的任何其他事情)来有效地做事,而不是依赖多次调用来operator++()
。
所以,你的答案是:std::for_each
并没有过时。可读性只是它要做的事情之一,但在迭代 STL 容器时,它仍然比任何 for 循环更有效。
这将是一个相当主观的话题,但就其价值而言,我同意你的看法。我认为使用语言结构比使用库结构要好得多,特别是当语言结构简洁易读时。(不过,在 c++11 之前,肯定有一个关于 for_each
可读性的争论)
- 重载运算符的范围是什么?它是否会影响作为类成员的集合的插入函数?
- 在 c++ 中解决段树以外的范围查询的有效方法是什么?
- 这个变量在 C++ 中的范围是什么?
- 访问提升:shared_ptr 主范围外崩溃,断言失败:px != 0.指针的正确用法是什么?
- 朋友声明的复杂范围界定规则有什么意义?
- "using namespace"子句在什么范围内有效?
- C++ 中的引用范围是什么?
- 在 C++20 计算范围内相邻对的最简洁明了的方法是什么?
- 私有在函数定义/实现的返回值范围内是什么意思 (c++)?
- "1L << count"是什么意思?如何使用超出"unsigned long long int? "范围的语句编号打印?
- 无法取消引用超出范围的向量迭代器 - 有什么问题?
- 在基于范围的循环中使用通用参考有什么好处?
- 什么概念允许容器在基于范围的 for 循环中使用?
- 范围操作员(::)在班级名称中做什么
- 什么是N位签名整数的最大保证范围
- 范围分辨率运算符在类型:: var的情况下返回什么
- 范围中的"range"和"view"有什么区别sv3 ts?
- C++ OpenCL:当缓冲区超出范围时,子缓冲区会发生什么情况?
- 在某些范围更新后获取整数数组的最终状态的有效算法是什么?
- C 中类声明的范围是什么?