2010-07-27 107 views
5

也許這個問題是微不足道的,但想着這第二次我不知道該怎麼做了以下真正的正確方法:迭代std :: vector(不帶迭代器)時使用哪種類型?

std::vector<K> v = ...; 
for(T i=0; i<v.size(); ++i) { 
    const K& t = v[i]; 
    // use t *and i* 
} 

什麼類型應該T是什麼? int,unsigned int,int32_t,size_t(這將是v.size()的類型)還是其他建議?請儘量考慮可移植性,錯誤傾向性和性能,並在您的答案中保持客觀。

編輯:我沒有選擇迭代器,因爲它也想明確地使用索引號。

回答

6

i的類型應該與返回值size()相同,即std::vector<K>::size_type。但是,在實踐中,size_t將會很好。如果你使用簽名的整數類型,那麼你的編譯器可能會在小於比較中警告有符號/無符號不匹配。

通常你會使用迭代器這個反正:

std::vector<K> v = ...; 
for (std::vector<K>::iterator i = v.begin(); i != v.end(); ++i) { 
    const K& t = *i; 
    // use t 
} 

或者C++ 0x中:

std::vector<K> v = ...; 
for (auto i = v.begin(); i != v.end(); ++i) { 
    const K& t = *i; 
    // use t 
} 

在回答您關於使用迭代器向量索引評論,考慮向量迭代器的恆定時間操作的std::distance()函數:

std::vector<K> v = ...; 
for (auto i = v.begin(); i != v.end(); ++i) { 
    const K& t = *i; 
    size_t index = std::distance(v.begin(), i); 
    // use t and index 
} 
+2

或者C++ 0x中:'爲(自動I:V){...}'(N2930):-) – 2010-07-27 09:24:44

+1

現在我的問題是,什麼更快/更清晰/可移植性:使用整數來迭代(並將其作爲索引直接使用)或使用迭代器和距離函數來計算索引? – Danvil 2010-07-27 09:30:43

+0

@Danvil:最有可能的,沒關係。兩者都包含一個簡單的增量和一個加法或減法。而在這兩種情況下,這兩種說法都不能進行同步。我期望分開增加i和迭代器的解決方案會稍微快一點,因爲它可以被並行化。但是,我懷疑這種差異在實踐中是可以衡量的。 – Sjoerd 2010-07-27 09:44:31

3

v.size返回的類型以及v[]預計的類型爲std::vector<K>::size_type

但是,請考慮使用迭代器:出界的風險較低,您可以使用標準庫算法。

3

類型T通常無關緊要,只要它與矢量大小一樣大。

在性能方面,應該沒有任何區別。

在錯誤傾向/便攜性方面,我建議使用符號整數,因爲如果你以某種方式減去i值,你會得到一個大的正數,這是很難檢查不是負數。但由於v.size()size_t,如果使用T的一個符號整數,並v具有≥2 (或2 )項目,該i將有可能成爲結束前無效。但是我認爲,如果矢量需要大得多(特別是在64位平臺上),那麼還有其他更大的問題,而不是選擇哪種類型的T。

從不使用int32_t作爲計數器。


(這些都是之前OP的編輯:)

但在你的情況你可能想用一個迭代器迭代來代替。

for (std::vector<K>::const_iterator cit = v.begin(); cit != v.end(); ++ cit) { 
    const K& t = *cit; 
    // ... 
} 

隨着Boost.Foreach你可以把這個爛攤子到

BOOST_FOREACH(const K& t, v) { 
    // ... 
} 

在C++ 0x中這將成爲一個built-in feature(§ [stmt.ranged]),但據我所知沒有編譯器支持它尚未:

for (const K& t : v) { 
    // ... 
} 

但是大多數聲稱支持C++ 0x的編譯器應該允許auto

for (auto cit = v.cbegin(); cit != v.cend(); ++ cit) { 
    const K& t = *cit; 
    // ... 
} 

或lambda表達式:

std::for_each(v.cbegin(), v.cend(), [](const K& t) { 
    ... 
}); 
+0

以及如何知道元素在這些案例中的位置?你是否認爲迭代器和額外的計數比使用數字迭代更好? – Danvil 2010-07-27 09:28:24

+0

@Danvil:通常我會保留2個變量,計數器和迭代器。如果你想遍歷非向量結構,這是必需的。但對於向量,'t = v [i]'和'i = distance(cit,begin)'具有相似的性能,並且都只涉及指針算術和位移。 – kennytm 2010-07-27 09:41:19

+0

如果我會使用int作爲迭代器類型,考慮到事實,size()是size_t,通常是無符號的,比較signed和unsigned整數是不是慢一點?另外,編譯器推導出這些惱人的警告之一,比較簽名與無符號整數。 – Danvil 2010-07-27 09:45:58