[英]iterator vs reverse_iterator
I'm using std::map
to store a lot of elements (pairs of elements) and I have a "little" doubt. 我正在使用
std::map
来存储很多元素(元素对),我有一点“怀疑”。 What is more efficient to iterate all elements over my std::map
, iterator
or reverse_iterator
? 在
std::map
, iterator
或reverse_iterator
上迭代所有元素的效率更高?
For the record, dereferencing reverse_iterator
on std::map
and std::set
containers is twice as slow as using iterator
-- with both -O3 gcc 3.4.6 and MSVC on Intel/AMD processors (almost 3x as slow on PPC architectures.) Same holds for const_reverse_iterator
vs. const_iterator
. 对于记录,在
std::map
和std::set
容器上解除引用reverse_iterator
速度是使用iterator
两倍 - 在Intel / AMD处理器上同时使用-O3 gcc 3.4.6和MSVC(在PPC体系结构上几乎是3倍。 )同样适用于const_reverse_iterator
与const_iterator
。 This is due to the fact that reverse_iterator
actually points to the tree node immediately following the tree node to be dereferenced, hence the extra work. 这是因为
reverse_iterator
实际上指向树节点后面的树节点被解除引用,因此额外的工作。 std::vector
iterators exhibit a much milder difference ( reverse_iterator
is only ~30% slower on PPC, virtually indistinguishable on Intel/AMD.) Incidentally, a std::vector
iterator is about 20x faster than a std::map
or std::set
iterator. std::vector
迭代器表现出更温和的差异(在PPC上, reverse_iterator
只慢约30%,在Intel / AMD上几乎无法区分。)顺便说一句, std::vector
迭代器比std::map
或std::set
快约20倍std::set
迭代器。
#include <set>
#include <vector>
#include <stdio.h>
#ifdef _WIN32
#include <sys/timeb.h>
#else
#include <sys/time.h>
#endif
#include <time.h>
#define CONTAINER std::set< int >
double
mygettime(void) {
# ifdef _WIN32
struct _timeb tb;
_ftime(&tb);
return (double)tb.time + (0.001 * (double)tb.millitm);
# else
struct timeval tv;
if(gettimeofday(&tv, 0) < 0) {
perror("oops");
}
return (double)tv.tv_sec + (0.000001 * (double)tv.tv_usec);
# endif
}
int main() {
int i, x = 0;
CONTAINER bla;
for (i = 0; i < 10000; bla.insert(bla.end(), i++)) ;
double t1 = mygettime();
for (i = 0; i < 100; ++i) {
for (CONTAINER::iterator it = bla.begin(); it != bla.end(); ++it) {
x ^= *it;
}
}
printf("forward: %f\n", mygettime() - t1);
double t2 = mygettime();
for (i = 0; i < 100; ++i) {
for (CONTAINER::reverse_iterator it = bla.rbegin(); it != bla.rend(); ++it) {
x ^= *it;
}
}
printf("reverse: %f\n", mygettime() - t2);
return 0;
}
Does it really matter? 真的有关系吗? these are the types of the micro optimizations you must try to avoid IMHO.
这些是您必须尝试避免恕我直言的微优化的类型。 Also, even if the iteration time changes for very large number of elements in the map, the fact that you are trying to iterate through all the elements of such a big map means that most probably you have chosen a wrong data structure.
此外,即使迭代时间因地图中的大量元素而发生变化,您尝试迭代这样一个大地图的所有元素这一事实意味着您很可能选择了错误的数据结构。
Unless you have profiled your code and found there to be a significant difference, I just wouldn't be concerned about it. 除非你已经对你的代码进行了分析并发现它们存在重大差异,否则我就不会担心它了。
"Premature optimization is the root of all evil."
“过早优化是万恶之源。” - Donald Knuth
- 唐纳德克努特
There will likely be no difference. 可能没有区别。 std::reverse_iterator is just a template shim that translates ++'s to --'s at compile time.
std :: reverse_iterator只是一个模板填充程序,可以在编译时将++转换为 - 。
For a vector or other contiguous storage container, a forward iterator might interact very slightly better with the cache than a reverse iterator would (unlikely you'd be able to detect it), but for a tree-based container it won't make any difference at all--there won't be any locality of reference to exploit. 对于向量或其他连续的存储容器,正向迭代器可能与高速缓存相比与反向迭代器相比会更好地交互(不太可能你能够检测到它),但对于基于树的容器,它不会产生任何完全不同 - 没有任何可供参考的地方。
Me think it does not make sense to use a reverse_iterator; 我认为使用reverse_iterator是没有意义的; it's counter intuitive.
这是反直觉的。
It would make the code harder to understand, someone will look at the code and go "wtf"; 它会使代码更难理解,有人会查看代码并转到“wtf”; and if you need to put a comment to explain why, it probably means it's not good code to start with.
如果你需要发表评论来解释原因,这可能意味着它不是一个好的代码。
I am wondering the need for iteration. 我想知道迭代的必要性。 Map holds the key-value pairs and normally you use it for the lookup.
Map包含键值对,通常用于查找。 If you still need to iterate the map for some reasons ( may be deleting pointers contained inside the map etc) then you can use std::for_each .
如果由于某些原因仍然需要迭代地图(可能是删除地图中包含的指针等),那么你可以使用std :: for_each 。 Forget the micro optimizations and you can try to increase the code readability.
忘记微优化,您可以尝试提高代码的可读性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.