在STL库中,一些容器具有迭代器,并且通常认为它们是迭代这些容器的优良方式,而不是简单的循环,例如。
for ( int i=0; i < vecVector.size(); i++ )
{
..
}
任何人都可以告诉我为什么以及在什么情况下我应该使用迭代器以及在什么情况下上面的代码片段?
答案 0 :(得分:27)
请注意,vector的通常实现不会使用“int”作为索引/大小的类型。因此,您的代码至少会引发编译器警告。
迭代器可以提高代码的通用性。
例如:
typedef std::vector<int> Container ;
void doSomething(Container & p_aC)
{
for(Container::iterator it = p_aC.begin(), itEnd = p_aC.end(); it != itEnd; ++it)
{
int & i = *it ; // i is now a reference to the value iterated
// do something with "i"
}
}
现在,让我们假设您将向量更改为列表(因为在您的情况下,列表现在更好)。您只需要更改typedef声明,然后重新编译代码。
如果您使用的是基于索引的代码,则需要重新编写代码。
迭代器应该被视为一种超级指针。 它“指向”值(或者,如果是地图,则指向键/值对)。
但它有移动到容器中下一个项目的方法。或者之前的。有些容器甚至提供随机访问(向量和双端队列)。
大多数STL算法适用于迭代器或迭代器范围(同样,因为通用性)。这里你将无法使用索引。
答案 1 :(得分:17)
使用迭代器可以让您的代码与容器的实现无关。如果您的容器的随机访问价格便宜,那么在性能方面没有太大区别。
但在很多情况下你不会知道是否是这种情况。如果你尝试在链表上使用你的方法,例如,使用下标,容器就必须在每次迭代时遍历列表以找到你的元素。
因此,除非您确定对容器的随机访问很便宜,否则请使用迭代器。
答案 2 :(得分:2)
如果使用迭代器作为函数的参数,则可以将其与所使用的“容器”类型分离。例如,您可以将函数的结果指向控制台输出而不是向量(下面的示例)。这个技巧可以非常强大,可以减少类之间的耦合。松散耦合的类更容易测试。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template <typename InputIterator, typename OutputIterator>
void AddOne(InputIterator begin, InputIterator end, OutputIterator dest)
{
while (begin != end)
{
*dest = *begin + 1;
++dest;
++begin;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
vector<int> data;
data.push_back(1);
data.push_back(2);
data.push_back(3);
// Compute intermediate results vector and dump to console
vector<int> results;
AddOne(data.begin(), data.end(), back_inserter(results));
copy(results.begin(), results.end(), ostream_iterator<int>(cout, " "));
cout << endl;
// Compute results and send directly to console, no intermediate vector required
AddOne(data.begin(), data.end(), ostream_iterator<int>(cout, " "));
cout << endl;
return 0;
}
答案 3 :(得分:1)
在您的示例中,对vecVector.size()的调用效率低于使用迭代器的效率。迭代器基本上封装了你不必担心迭代的容器的大小。此外,迭代器不必按顺序排列。它只需以它认为合适的方式响应.next调用。
答案 4 :(得分:1)
嗯,一方面,如果你把那个矢量变成一个列表,上面的内容就不再适用了。
迭代器允许您创建不需要知道它们所使用的容器类型的函数模板。您甚至可以执行以下操作:
#include <algorithm>
void printvalue(double s)
{
// Do something with s
}
int _tmain(int argc, _TCHAR* argv[])
{
double s[20] = {0};
std::for_each(s, s+20, printvalue);
return 0;
}
那是因为标准指针也是for_each的有效迭代器。
戴夫
答案 5 :(得分:1)
迭代器主要是更高级别的抽象。
您的代码段假定可以对容器编制索引。这适用于std::vector<>
和其他一些容器,例如原始数组。
但是std::set<>
完全没有索引,std::map<>
的索引运算符会将提供给它的任何参数插入到地图中 - 而不是for
- 循环中的预期行为。
此外,性能问题仅在测量和证明时才会出现问题。