2017-08-02 101 views
0

我正在使用std::vectorC++來存儲一些項目&稍後檢索它們。以下是我如何遍歷我的向量。如何在重複循環中循環std :: vector

std::vector<some_object> some_vector; 
some_vector.resize(10); 

for (auto it = some_vector.begin(); it != some_vector.end(); ++it) { 
    int current_it_index = std::distance(some_vector.begin(), it); 
} 

我需要每次迭代的索引。因此,如上所示,每次迭代獲取它。

上述循環行之有效但我通過無限循環矢量要循環。我怎樣才能做到這一點?

現在,我明白問題來了,如果讓它在重複循環中運行,如何停止運行循環。我在考慮使用std::atomic<bool>作爲變量來發信號&跳出循環,這應該工作得很好?

PS:請注意,我已將std::vector作爲示例容器來解釋問題。如果建議的解決方案也可以在std::array或其他容器上工作,那將是非常好的。

+3

一個簡單的'while'循環可以做到這一點。不要過度綁定它,只需將當前的'for'循環包裝到'while'循環中,該循環將檢查'std :: atomic '。然而,它可以僅使用for循環來完成,您只需要更改兩件事:1)在最後復位迭代器,2)檢查您提到的std :: atomic 以便知道何時停止。 – DimChtz

+1

你想'current_it_index'在它開始再次通過矢量或者它應該不斷增加之後重置爲'0'嗎?這種聲音也是一個XY問題。如果你告訴我們你爲什麼這樣做,我們可能會指出你有什麼不同。 – NathanOliver

+0

明白了。 'for(auto it = some_vector.begin();; ++ it){int current_it_index = std :: distance(some_vector.begin(),it); if(it == some_vector.end()-1)it = some_vector.begin(); }' –

回答

3
std::vector<some_object> some_vector; 
some_vector.resize(10); 
bool quit = false; 
while (!quit) { 
    for (auto& e:some_vector) { 
    if (quit) break; 
    std::size_t i = std::addressof(e)-some_vector.data(); 
    // ... 
    } 
} 
1

迭代通過具有2個元素數量的數組的數組的常用技巧是簡單地迭代計數器並使用掩碼操作。

size_t counter = 0; 
const size_t mask = some_vector.size() - 1U; 

while (!quit) { 
    size_t i = counter++ & mask; 
    do_something(some_vector[i]); 
} 

如果該數組不是2的冪,則可以執行模算術,而不是屏蔽自由運行的計數器。

size_t i = 0; 
const size_t n = some_vector.size(); 

while (!quit) { 
    do_something(some_vector[i++]); 
    i %= n; 
} 

如果使用非隨機訪問容器,需要迭代器和索引,然後你可以實現兩個循環。這將避免在非隨機訪問迭代器上計算distance的開銷。

for (;;) { 
    size_t idx = 0; 
    for (auto it = some_container.begin(); 
     it != some_container.end(); 
     ++it) { 
     do_something(it, idx++); 
    } 
+0

這得到一個索引,而不是一個迭代器,它可能適用於'矢量',但不適用於'list'或任何其他非連續的數據結構。 –

+0

它適用於'deque',它是非連續的。 – jxh

+0

夠公平的;我的評論是不準確的。這本質上並不正確;如果沒有'operator []',at()'或其他將'size_t'轉換爲元素的方法,這是行不通的。 –

1

如果我理解正確的,你想要的是,當您到達容器的最後一個元素,只需跳到容器的開頭一次。我們可以很容易地編碼:

auto first = std::begin(c); 
const auto last = std::end(c); 
std::size_t idx = 0; 

while (!should_exit()) { 
    do_something(idx); 

    ++idx; 
    if (++first == last) { // reset 
     idx = 0; 
     first = std::begin(c); 
    } 
} 

這應該適用於任何STL風格的容器。同時擁有迭代器和索引可能是不必要的,但這是一個KISS解決方案,可用於非隨機訪問容器,如std::list以及向量/數組。

+0

一般而言,此代碼具有危險的依賴性,即do_something()不會使迭代器失效(或者修改容器)。 –