性能 - 使用迭代器还是指针遍历向量?

3

我正在编写一个需要尽可能发挥性能的应用程序。我的IDE(和编译器)是VS2012。

我注意到,当我迭代向量时,与迭代器相比,指针解决方案在速度上要快得多。为什么会这样呢?我的意思是,迭代器基本上是相同的东西。至少应该是。

看看这个例子:

std::vector<int> v;
for (std::vector<int>::iterator it = v.begin(); it != v.end(); it++) {
    // Do stuff with *it
}

for (int* i = &v[0], i <= &v[v.size()-1]; i++) {
    // Do stuff with *i
}

编译器是否需要进行优化?我正在使用所有标准设置,因此已启用-O2。提前致谢。

编辑: 我正在发布中编译,并使用Ctrl+F5运行(不带调试)。

编辑2: 实际的源代码是快速排序的实现。这里是完整源代码的链接,非常简短,请查看。


1
你可能正在调试模式下编译,迭代器执行断言。 - ronag
1
请查看调试版本和优化版本生成的汇编代码之间的差异。 - Peter Wood
1
请检查您的_ITERATOR_DEBUG_LEVEL设置。 - Bo Persson
我的指针版本在快速排序的分区位上与使用迭代器的std::partition不同。我通过测量函数调用的执行时间来进行性能分析。唯一的区别是分区位,这导致迭代器的速度慢了约30%。这里有一个链接:http://pastebin.com/5KV2RWZA。 - Eric
@Eric 但是,那是完全不同的代码! - Peter Wood
显示剩余5条评论
3个回答

4
我正在编写一款需要尽可能快速运行的应用程序。使用性能分析工具,查看真正的瓶颈在哪里。当然,在优化代码(发布模式)中进行。
-O2不是VS2012中的全部内容:有几个#defines可以操作标准容器迭代器与边界检查和其他安全检查之间的行为。您可能需要查找它们(“checked iterators”和“secure SCL”可能会带您到正确的网站)并相应设置。
但我非常怀疑遍历容器将成为您的瓶颈,还将有其他更敏感于性能问题的代码部分。

2
可能的一个原因是你使用的是后增迭代器而不是前增迭代器。尝试使用以下代码替代:
for (std::vector<int>::iterator it = v.begin(); it != v.end(); ++it)

这可能不会提高您的速度,因为一些(也许是大多数)编译器会优化掉这个问题。然而,有时当您进行后置递增时,必须创建旧迭代器值的临时副本,以允许它在循环中返回您期望的值。无论如何,这是值得尝试的。


1

提高性能的一种简单方法是不在每次迭代中执行end方法,同时使用++it而不是it++

例如:

std::vector<int> v;
const std::vector<int>::iterator end = v.cend();
for (std::vector<int>::iterator it = v.begin(); it != end; ++it) {
    // Do stuff with *it
}

2
从实际测量(使用g ++,而不是VC ++),无论您使用++ i还是i ++都无关紧要。 然而,在循环之外移动对end()的调用确实会产生明显的差异。在C++11之前,使用const迭代器也可以避免类型转换(如果v.end()返回非const迭代器)。出于这些原因,我习惯编写for(std::vector<int>::const_iterator current=v.begin(), end=v.end();current!=end;++current) - James Kanze

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接