cai*_*rol 409 c++ iterator coding-style
我正在迭代一个向量,需要迭代器当前指向的索引.AFAIK这可以通过两种方式完成:
it - vec.begin()
std::distance(vec.begin(), it)
这些方法的优点和缺点是什么?
Unc*_*ens 522
我更倾向于it - vec.begin()
出于Naveen给出的相反原因:如果将向量更改为列表,则无法编译.如果在每次迭代中执行此操作,您可能很容易将O(n)算法转换为O(n ^ 2)算法.
如果在迭代期间没有在容器中跳转,则另一个选项是将索引保持为第二个循环计数器.
注意:it
是容器迭代器的通用名称std::container_type::iterator it;
.
Nav*_*een 126
我更喜欢,std::distance(vec.begin(), it)
因为它允许我更改容器而不需要任何代码更改.例如,如果您决定使用std::list
而std::vector
不是提供随机访问迭代器,则代码仍将编译.由于std :: distance根据迭代器特性选择最佳方法,因此您也不会有任何性能下降.
jal*_*alf 72
正如UncleBens和Naveen所表明的那样,两者都有充分的理由.哪一个"更好"取决于您想要的行为:您是否希望保证恒定时间行为,或者您是否希望它在必要时回退到线性时间?
it - vec.begin()
需要持续时间,但是operator -
只在随机访问迭代器上定义,因此代码将不会使用列表迭代器进行编译.
std::distance(vec.begin(), it)
适用于所有迭代器类型,但如果在随机访问迭代器上使用,则只能是常量操作.
两者都不"更好".使用满足您需求的那个.
Eli*_*sky 11
我喜欢这个:it - vec.begin()
因为对我来说它清楚地说"距离开始的距离".对于迭代器,我们习惯于在算术方面进行思考,因此-
符号是这里最清晰的指标.
如果您已经限制/硬编码的算法,使用std::vector::iterator
和std::vector::iterator
而已,它并没有真正不管你最终会采用哪种方法.您的算法已经具体化,超出选择其中一个可以产生任何差异的点.他们都做了完全相同的事情.这只是个人喜好的问题.我个人会使用显式减法.
另一方面,如果你想在算法中保持更高的通用性,即允许将来某天可能应用于其他迭代器类型的可能性,那么最好的方法取决于你的意图.这取决于您希望在此处使用的迭代器类型方面的限制程度.
如果使用显式减法,则算法将限制为一个相当窄的迭代器类:随机访问迭代器.(这是你现在得到的std::vector
)
如果使用distance
,您的算法将支持更广泛的迭代器类:输入迭代器.
当然,distance
非随机访问迭代器的计算通常是低效操作(同样,对于随机访问迭代,它与减法一样有效).您可以自行决定算法是否对非随机访问迭代器有意义.由此产生的效率损失对于使算法完全无用是毁灭性的,然后你应该更好地坚持减法,从而禁止低效使用并迫使用户为其他迭代器类型寻找替代解决方案.如果非随机访问迭代器的效率仍处于可用范围内,那么您应该使用distance
并记录该算法在随机访问迭代器中更好地工作的事实.
根据http://www.cplusplus.com/reference/std/iterator/distance/,由于vec.begin()
是随机访问迭代器,因此距离方法使用-
运算符。
所以答案是,从性能的角度来看,它是相同的,但distance()
如果有人必须阅读和理解你的代码,也许使用更容易理解。