[英]Should I iterate a vector by iterator or by access operator?
我有一個聲明為的向量
std::vector<int> MyVector;
MyVector.push_back(5);
MyVector.push_back(6);
MyVector.push_back(7);
我應該如何在for循環中使用它?
通過迭代器迭代它?
for (std::vector<int>::iterator it=MyVector.begin(); it!=MyVector.end(); ++it)
{
std::cout << "Vector element (*it): " << *it << std::endl;
}
或者通過它的訪問迭代器?
for (std::vector<int>::size_type i=0; i<MyVector.size(); i++)
{
std::cout << "Vector element (i) : " << MyVector.at(i) << std::endl;
}
在我在互聯網上找到的例子中都使用了它們。 在所有條件下,其中一個優於另一個嗎? 如果沒有,我什么時候應該更喜歡其中一個呢?
第一種格式是更通用的格式,用於迭代標准庫容器,因此它更常見,更直觀。 如果你需要更改容器,那么這個迭代代碼仍然沒有受到影響。它將適用於每個標准庫容器類型,因此它為您提供了更多通用代碼。
在第二種格式中, std::vector::at()
每次迭代時都會檢查邊界,因此它可能對性能有點不利 。 由於沒有涉及邊界檢查,因此第一種格式中不存在此開銷。請注意,使用operator[]
的情況也是如此。
請注意,性能滯后不會像您注意到的那樣多,除非您正在操作大量數據。
使用std::vector's [] operator
可能更快,因為std::vector::at()
for循環中使用std::vector::at()
檢查向量的大小兩次(在for循環和std :: vector :: at()的邊界內檢查)。
第一種方法可以在其他容器中使用,因此在更改容器類型時可以幫助您。
如果使用C ++ 11,請使用基於范圍的循環。
首先,如果你有C ++ 11,請使用基於范圍的:
for (auto i : MyVector)
{
std::cout << i;
}
或C ++ 03中的BOOST_FOREACH
:
BOOST_FOREACH(int& i, MyVector)
{
std::cout << i;
}
或者std::copy
:
std::copy(MyVector.begin(),
MyVector.end(),
std::ostream_iterator<int>(std::cout, "\n"));
至於手頭的問題, at()
檢查索引是否在邊界內,如果不是則拋出異常。 所以,除非你需要額外的檢查,否則不要使用它。 你擁有它的第一種方式是標准的並且效果很好。 有些人很迂腐,甚至寫得像:
for (std::vector<int>::iterator it=MyVector.begin(), end = MyVector.end(); it!= end; ++it)
{
std::cout << "Vector element (*it): " << *it << std::endl;
}
在上面我緩存了end
迭代器而不是調用end()
每個循環。 不知道這是否真的會帶來性能差異,我不知道。
沒有“一個優於另一個”(除了你幾乎從不想使用at()
- at()
只適用at()
你可以真正從錯誤中恢復的東西)。 迭代器與索引的使用主要是樣式和您傳遞的消息之一。 更慣用的C ++做事方式是迭代器,但來自其他背景的人(例如,數學家)會發現索引更具慣用性。
有一些真正的區別:
迭代器習語可以與其他類型的容器一起使用。 如果您真的有可能使用其他容器,這可能是相關的。
索引習慣用法可以為幾個不同的容器使用單個索引。 如果您正在迭代幾個具有相同大小的vector
,則使用索引慣用法會更清楚地表明您正在訪問每個vector
的相同元素。 (同樣,這似乎最常出現在數學應用中。)
最后,每當你真正進行隨機訪問或以任何方式計算元素時,使用索引可能更直觀。 (在這種情況下,您可能希望在int
進行計算,僅在最后時刻轉換為size_t
。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.