C++ 迭代器。。为什么要使用它们?
在STL库中,一些容器具有迭代器,通常认为迭代器是遍历这些容器的一种优越方法,而不是简单的for循环,例如C++ 迭代器。。为什么要使用它们?,c++,stl,iterator,C++,Stl,Iterator,在STL库中,一些容器具有迭代器,通常认为迭代器是遍历这些容器的一种优越方法,而不是简单的for循环,例如 for ( int i=0; i < vecVector.size(); i++ ) { .. } for(int i=0;i
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没有订阅运算符。对,集合甚至可能不支持随机访问——因此子脚本可能甚至不起作用。迭代器无论如何都会起作用。注意:这段代码在“范围”库中特别强大。可以使用在迭代器对上工作的算法除了流和其他值生成器之外,还可以使用容器中的子集生成。请参阅“范围”和“迭代器”库。