2013-02-23 66 views
0

从我所学到的方法来遍历容器中,如性病::矢量STD容器,是使用迭代器,因为这:迭代比使用标准

for(vector<int>::iterator it = numbers.begin(); it != numbers.end(); it++) 

我的问题是,为什么不不迭代容器for,它速度更快,因为不需要调用函数numbers.begin()numbers.end()
从我的尝试,我发现使用for是更快的X 30,从使用迭代器。
我写了这个代码:

vector<int> numbers; 
for (int i = 0; i < 5000000; i++) 
{ 
    numbers.push_back(i); 
} 

time_t t = time(0); 
struct tm * now = localtime(&t); 
cout << now->tm_hour << ":" << now->tm_min << ":" << now->tm_sec << "\n"; 

for(vector<int>::iterator it = numbers.begin(); it != numbers.end(); it++) 
{ 
    *it = 7; 
} 

t = time(0); 
now = localtime(&t); 
cout << now->tm_hour << ":" << now->tm_min << ":" << now->tm_sec << "\n"; 

int size = numbers.size(); 
for (int i = 0; i < size; i++) 
{ 
    numbers[i] = i; 
} 

t = time(0); 
now = localtime(&t); 
cout << now->tm_hour << ":" << now->tm_min << ":" << now->tm_sec; 

输出是:

19:28:25 
    19:28:56 
    19:28:57 
+0

您似乎认为,标准的容器是可转位(即'号[I]'),那肯定是不规范的做法,但 – 2013-02-23 19:28:07

+0

您正在使用的“标准”'for'在这两种情况下,在你的榜样异常。 – 2013-02-23 19:30:28

+3

您是否启用编译器优化?在调试构建和发布构建之间,'vector :: iterator'的行为可能会有很大差异。 – aschepler 2013-02-23 19:32:13

回答

2

看看你的数字 - 30秒来迭代一个简单的向量?这是CPU时间的永恒。那里有问题。

几点建议:

  • 的载体需要19MB〜。这并不多,但可能会导致堆碎片,或者如果在计算机上加载了许多其他应用程序,则可能会交换VM。要获得可靠的号码,请尽可能多地关闭应用程序,并确保您的系统处于闲置状态。

  • 的COUTS都定时器里面,所以你要衡量的iostream库的部件的性能。在定时部分之外进行cout,之后您采取停止时间。

  • 一个一第二时钟不是性能度量不够精确。使用timeval和gettimeofday()来获得微秒精度。

  • 只有一个迭代的载体,我所看到的运行之间的大diffences。为了获得更多可重复的结果,多次迭代向量(如500次)。 (这比使用较大的载体,这可能会导致交换/碎片问题更好。)

  • 开启的优化(例如,克++ -O3)。循环会跑得快得多,时间差会少得多。内联优化可能更有助于std :: vector <>代码。

随着这些变化(如下图),在我的电脑上,迭代器比没有优化indicies 4倍速度较慢,但​​与-O1和几乎相同的使用-O3。

#include <iostream> 
#include <sys/time.h> 
#include <vector> 
using namespace std; 

const unsigned N_REPS = 500; 
const unsigned N_ITEMS = 5000000; 

int print_elapsed(timeval start) 
{ 
    timeval stop; 
    gettimeofday(&stop, NULL); 
    int elapsed = (stop.tv_sec * 1000000 + stop.tv_usec) - (start.tv_sec * 1000000 + start.tv_usec); 
    cout << elapsed << "us" << endl; 
    return elapsed; 
} 

int main() 
{ 
    vector<int> numbers; 
    numbers.reserve(N_ITEMS); // avoid heap fragmentation 
    for (int i = 0; i < N_ITEMS; ++i) 
     numbers.push_back(i); 

    timeval start; 
    gettimeofday(&start, NULL); 

    for (unsigned r = 0; r < N_REPS; ++r) 
     for (vector<int>::iterator it = numbers.begin(); it != numbers.end(); ++it) 
      *it = r; 

    int elapsed0 = print_elapsed(start); 
    gettimeofday(&start, NULL); 

    unsigned size = numbers.size(); 
    for (unsigned r = 0; r < N_REPS; ++r) 
     for (unsigned i = 0; i < size; ++i) 
      numbers[i] = r; 

    int elapsed1 = print_elapsed(start); 
    cout << 100 * float(elapsed1)/elapsed0 << '%' << endl; 

    return 0; 
} 
+0

因此,你最好总结使用standatd,没有迭代器? – user1544067 2013-02-23 20:29:47

+0

使用此编译器(gcc 4.4.6),在启用优化的情况下,使用迭代器和简单整数索引之间不存在有意义的性能差异。我怀疑这对其他编译器会是真的。所以我的建议是启用优化。 – 2013-02-24 13:28:22

1

使用迭代器提供给您,即使您更改容器类型到另一个迭代代码保持不变的灵活性。这是因为所有的标准库容器都提供迭代器。在某种程度上,它使您有机会编写更多通用代码。

+0

但是什么更好的方法来迭代容器? – user1544067 2013-02-23 19:30:53