迭代向量的元素时,最好使用迭代器而不是索引(参见Why use iterators instead of array indices?) .
std::vector<T> vec;
std::vector<T>::iterator it;
for ( it = vec.begin(); it != vec.end(); ++it )
{
// do work
}
但是,可能需要在循环体中使用索引 . 考虑到性能和灵活性/可扩展性,在这种情况下,下列哪一项更可取?
- 恢复索引循环
std::vector vec;
size_t i;
for ( i = 0; i < vec.size(); ++i )
{
// use i
}
- 计算偏移量
std::vector vec;
std::vector::iterator it;
for ( it = vec.begin(); it != vec.end(); ++it )
{
size_t i = it - vec.begin();
// use i
}
- 使用std :: distance
std::vector vec;
std::vector::iterator it;
for ( it = vec.begin(); it != vec.end(); ++it )
{
size_t i = std::distance( vec.begin(), it );
// use i
}
7 回答
如果您计划仅使用向量,则可能需要切换回索引循环,因为它比迭代器循环更清楚地传达您的意图 . 但是,如果将来程序的演变可能导致容器的更改,则应该坚持使用迭代器并使用std :: distance,这可以保证与所有标准迭代器一起使用 .
使用std :: distance更通用,因为它适用于所有迭代器,而不仅仅是随机访问迭代器 . 在随机访问迭代器的情况下,它应该与它一样快 - vec.begin() .
它 - vec.begin()基本上是指针算术 .
std::distance(vec.begin(), it)将指向
it
指向的索引,假设它指向vec
.卡尔
恢复到索引循环 .
基本上在90%的情况下,迭代器是优越的,这是10%中的一个 . 通过使用迭代器,您将使代码更复杂,因此更难以理解,因为首先使用迭代器的完整原因是为了简化代码 .
您缺少一个解决方案:保留索引以备不时之需,但不要将其用作循环条件 . 也适用于列表,成本(每个循环)是O(n)和一个额外的寄存器 .
出于未来的发展原因,我总是倾向于使用迭代器 .
在上面的例子中,如果您可能决定将std :: vector替换为std :: set(可能需要一个唯一的元素集合),使用迭代器和distance()将继续工作 .
我非常确定任何性能问题都会被优化到可以忽略不计的程度 .
对于向量,我总是使用整数方法 . 向量中的每个索引与数组查找的速度相同 . 如果我将要使用该值很多,为方便起见,我创建了对它的引用 .
矢量迭代器在理论上可能比索引略快,因为它们使用指针算法迭代列表 . 但是,通常我发现可读性值得最小的运行时差异 .
我将迭代器用于其他容器类型,有时候当你不需要循环变量时 . 但是如果你需要循环变量,除了让你的循环更难输入外,你什么都不做 . (我等不及c 0x的自动......)