2016-05-31 107 views
0

我最近閱讀的一些帖子聲稱for(const auto &it : vec)與使用較長的迭代器語法for(std::vector<Type*>::const_iterator it = vec.begin(); it != vec.end(); it++)相同。但是,我遇到this post,說他們不一樣。將const auto&轉換爲迭代器

目前,我試圖擦除for循環中的一個元素,使用後,並想知道是否有任何方法將const auto &it : nodes轉換爲std::vector<txml::XMLElement*>::iterator

代碼中的問題:

std::vector<txml2::XMLElement *> nodes; 
//... 
for (const auto &it : nodes) 
{ 
    //...  
    nodes.erase(it); 
} 

我敢肯定,我可以改寫std::vector<txml2::XMLElement*>作爲一個常量指針,但不會喜歡,因爲這個代碼僅僅是在當下調試。

回答

4

您不應該試圖將基於循環的範圍內的範圍聲明轉換爲迭代器,然後在迭代時刪除它。即使在迭代時調整迭代器也很危險,而應該依賴算法。您應該使用Erase-remove idom
您可以使用remove_if

它看起來是這樣的:

nodes.erase(std::remove_if(nodes.begin(), nodes.end(), [](auto it){ 

    //decide if the element should be deleted 
    return true || false; 

    }), nodes.end()); 

目前在技術規範,爲erase_if
這是上面顯示的相同的行爲更清潔的版本:

std::erase_if(nodes,[](auto it){ 

    //decide if the element should be deleted 
    return true || false; 
}); 
+0

謝謝,這是一個巨大的幫助。最終使用'set_difference'結束了,但這讓我走上了正確的道路。 – ZeroPhase

1

你沒有得到一個迭代器,但該元素的引用。除非你想用它做一個std::find,否則很難得到一個迭代器。

向量很好,所以你可以增加一個計數器每個元素和做nodes.begin() + counter獲得迭代器,但它有點擊敗點。

而且擦除迭代器會導致你的矢量結束後進行迭代的for循環,您可以測試這個代碼:

#include <iostream> 
#include <vector> 

using namespace std; 

int main() { 
    vector<int> v = {0,1,2,3,4,5,6}; 

    for (int x : v) { 
     cout << x << endl; 

     if (x == 2) { 
      v.erase(v.begin() + 2); 
     } 
    } 
    return 0; 
} 

如果你想使用迭代器,只是做一個循環與他們如果除了要刪除一箇中循環,你必須遵循this answer

for (auto it = res.begin() ; it != res.end();) { 
    const auto &value = *it; 

    if (condition) { 
    it = res.erase(it); 
    } else { 
    ++it; 
    } 
} 

注意,你不需要指定整個類型的迭代器,auto作品一樣好。