迭代程序在C++中的重要性
Importance of Iterators In C++
这似乎是一个奇怪的问题,但我今天和一位朋友聊了聊,他对当今的C++程序员以及他们如何做得不太好大吵大闹。他说,他最讨厌的是在这样的代码中滥用迭代:
for(int i = 0; i<((int) someVector.size()); ++i){
//Something here
}
而不是更传统的
vector::iterator i;
for(i = someVector.begin(); i!=someVector.end(); ++i){
//Something here
}
虽然我理解这两种方法,但第二种方法优于第一种方法有什么特别的原因吗?是表演吗?还是其他因素?
提前谢谢。
这两种风格都不好。
第一个有一个无用和危险的演员阵容。
第二种方法允许迭代变量泄漏到循环的范围之外,并且不使用相等测试,而是在迭代器上使用后增量,这会产生无用的副本。
更好的是:
using std::begin, std::end;
for( auto it = begin(container), end_it = end(container); it != end_it; ++it )
这适用于任何STL容器、数组以及提供begin
和end
辅助函数的任何容器。
对于vector
,两者之间几乎没有区别。然而,如果您想迭代一个数据结构,比如set
,它根本没有随机访问,那么使用迭代器的第二个选项将是唯一明智的选择。
C++标准库竭尽全力使"迭代器"接口在许多不同类型的容器上尽可能一致。
在某些数据结构中,计算大小可能效率低下。根据优化器所能做的工作,这可能最终会为循环的每次迭代调用size()方法。当你使用第二段代码时,你不依赖于调用一个方法来计算大小,而你真正想要的只是知道你是否已经到达了末尾。
例如,考虑一个链表。除非链表被设计为在内部保持计数,否则必须遍历整个列表才能找到大小。此外,对于数据结构,没有办法使用索引来获取值。在这种情况下,您必须使用正确的迭代器方法。
使用迭代器通常不会带来真正的性能提升。可能更少。然而,与迭代的"C方法"相比,它们有一些潜在的优势:
1) 通过迭代器抽象容器可能更容易。由于我们在每次迭代中都要处理一个指针,如果容器类型需要更改,并且通过索引访问元素的形式发生了变化(或者因为不可能随机访问而不可能),迭代器可以节省一些乏味的编辑。
2) 您可以避免在每次迭代中使用size()
。尽管你可以预先计算一次,但最好完全避免。
3) 您基本上要处理一个指向正在遍历的容器中每个元素的指针。这比索引更好(至少对我来说是这样),而且可能更紧凑。
首先,我要注意的是,大多数代码根本不应该有显式循环。如果你要对一个集合进行操作,你应该使用一个算法。如果其中一个标准算法不能完成任务,你通常仍然应该实现你需要的算法,然后在需要的地方应用该算法(但如果你开始注意,你可能会惊讶于标准算法的工作频率)。
如果您确实需要编写一个显式循环,可以考虑使用基于范围的循环:
for (auto i : someVector)
// ...
然而,大多数时候,这应该是在算法的实现中。
- C++类 公共和私人领域的重要性
- 我想了解为什么在这个例子中使用引用函数?或者引用在c++函数中的重要性
- 在下面函数的返回中添加 const 限定符的重要性是什么?
- 使变量成为常数的重要性是什么?
- 类相对于数据结构的重要性
- BFS中队列大小的重要性
- 了解 QPainter 在 QOpenGLWidget 的 paintEvent 函数中的重要性
- 括号((c))中括号的重要性
- "this"的重要性
- 静态对象在类中的重要性以及它们与一般对象的区别
- 线程的单独堆栈空间的重要性
- 在 <conio.h> 中使用 _getch(),对"_"的重要性
- [C++]动态分配的重要性
- "&"运算符在此C++代码中的重要性
- 估计的重要性
- 初始化字符时空字符的重要性
- ThreadId 在 CreateThread() c++ 中的重要性
- 在 C 语言中,外部存储类说明符的重要性和用法
- 迭代程序在C++中的重要性
- 有人可以解释一下使用库中uint32_t的重要性<stdint.h>吗?