C++ 迭代器。。为什么要使用它们?

C++ 迭代器。。为什么要使用它们?,c++,stl,iterator,C++,Stl,Iterator,在STL库中,一些容器具有迭代器,通常认为迭代器是遍历这些容器的一种优越方法,而不是简单的for循环,例如 for ( int i=0; i < vecVector.size(); i++ ) { .. } for(int i=0;i

在STL库中,一些容器具有迭代器,通常认为迭代器是遍历这些容器的一种优越方法,而不是简单的for循环,例如

for ( int i=0; i < vecVector.size(); i++ )
{

..

}
for(int i=0;i

有人能告诉我为什么以及在什么情况下我应该使用迭代器,在什么情况下请使用上面的代码片段吗?

使用迭代器可以让您的代码不知道容器的实现。如果容器的随机访问比较便宜,那么在性能方面就没有多大区别

但在很多情况下,你不知道情况是否如此。如果您尝试在链表上使用您的方法,例如,使用订阅,那么容器必须在每次迭代中遍历链表才能找到您的元素


因此,除非您确定对容器的随机访问是廉价的,否则请使用迭代器。

在您的示例中,调用vecVector.size()的效率低于使用迭代器。迭代器本质上封装了您不必担心被迭代的容器的大小。此外,迭代器不必按顺序进行。它只需以它认为合适的任何方式响应.next调用。

好吧,首先,如果将该向量转换为一个列表,上述方法将不再有效

迭代器允许您创建不需要知道其使用的容器类型的函数模板。您甚至可以执行以下操作:

#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;
}
#包括
无效打印值(双s)
{
//用手指做点什么
}
int _tmain(int argc,_TCHAR*argv[]
{
双s[20]={0};
std::每个_(s,s+20,打印值);
返回0;
}
这是因为标准指针也是每个元素的有效迭代器


Dave

注意,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 std::vector容器;
无效剂量测定(容器和p_aC)
{
for(Container::iterator it=p_aC.begin(),itEnd=p_aC.end();it!=itEnd;++it)
{
int&i=*it;//i现在是对迭代值的引用
//用“我”做点什么
}
}
现在,让我们假设您将向量更改为列表(因为在您的示例中,列表现在更好)。您只需要更改typedef声明,然后重新编译代码

如果您使用了基于索引的代码,则需要重新编写

通道 迭代器应该被看作是一种超级指针。 它“指向”值(或者,在映射的情况下,指向键/值对)

但它有方法移动到容器中的下一项。或者上一个。有些容器甚至提供随机访问(vector和deque)

算法
大多数STL算法在迭代器或迭代器范围上工作(同样,由于泛型性)。您将无法在此处使用索引。

如果您使用迭代器作为函数的参数,则可以将其与所使用的“容器”类型解耦。例如,您可以将函数的结果定向到控制台输出,而不是向量(下面的示例)。这个技巧对于减少类之间的耦合非常有效。松散耦合的类更容易测试

#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;
}
#包括
#包括
#包括
使用名称空间std;
模板
void AddOne(输入迭代器开始、输入迭代器结束、输出迭代器结束)
{
while(开始!=结束)
{
*dest=*开始+1;
++目的地;
++开始;
}
}
int _tmain(int argc,_TCHAR*argv[]
{
矢量数据;
数据。推回(1);
数据。推回(2);
数据。推回(3);
//计算中间结果向量并转储到控制台
矢量结果;
AddOne(data.begin()、data.end()、back_inserter(results));
复制(results.begin()、results.end()、ostream_迭代器(cout,“”);

cout迭代器主要是更高级别的抽象

您的代码段假定容器可以被索引。这对于
std::vector
和一些其他容器(例如原始数组)是正确的

但是
std::set
完全缺少索引,并且
std::map
的索引操作符将向其提供的任何参数插入到映射中,而不是
for
循环中的预期行为


而且,性能问题只有在经过测量和证明后才会出现。

哪些STL容器没有迭代器?根据STL,如果类型有相关的迭代器类型,那么它就是一个容器,因此根据定义,没有迭代器类型。我不认为效率较低。编译器将通过调用size()对其进行优化循环外部。此外,大小是向量的一个属性,总是已知的,并且永远不需要计算,就像end()一样。如果在循环内部向向量添加一个项,会怎么样?当然,它不会在循环外部对其进行优化,但也不会使用end()进行优化循环之外。所以仍然没有区别。我认为std::list没有订阅运算符。对,集合甚至可能不支持随机访问——因此子脚本可能甚至不起作用。迭代器无论如何都会起作用。注意:这段代码在“范围”库中特别强大。可以使用在迭代器对上工作的算法除了流和其他值生成器之外,还可以使用容器中的子集生成。请参阅“范围”和“迭代器”库。