2013-02-23 64 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