2013-04-23 66 views
6

以下代碼按預期方式工作(測試通過),但我不知道以這種方式使用迭代器在C++中被認爲是不好的做法,或者它可以。使用迭代器將std :: vector添加到自己的元素中

也許這是專門針對std::vector和其他集合的行爲不同,最佳實踐因集合(甚至它們的實現)而異?

在其他語言中肯定不行,大多數情況下更改集合會使迭代器失效並拋出異常。

BOOST_AUTO_TEST_CASE (ReverseIteratorExample) { 
    std::vector<int> myvector; 
    for(int i = 0; i < 5; i++) 
    { 
     myvector.push_back(i); 
    } 

    // is this generally a bad idea to change the vector while iterating? 
    // is it okay in this specific case? 
    myvector.reserve(myvector.size() + myvector.size() - 2); 
    myvector.insert(myvector.end(), myvector.rbegin() + 1, myvector.rend() -1); 

    int resultset [8] = { 0,1,2,3,4,3,2,1 }; 
    std::vector<int> resultVector(resultset, resultset + sizeof(resultset)/sizeof(resultset[0])); 
    BOOST_CHECK_EQUAL_COLLECTIONS(myvector.begin(), myvector.end(), resultVector.begin(), resultVector.end()); 
} 

總結問題:

  1. 這通常是一個壞主意來改變,而迭代向量?
  2. 在這個特定情況下可以嗎?
  3. 這是特定的std::vector和其他集合的行爲有所不同嗎?
  4. 不同集合(甚至是其實現)之間的最佳實踐是否有所不同?
+0

有這個真正有趣的SO問題及其答案,我總是在有疑問時提及它:http://stackoverflow.com/questions/4114503/rules-for-iterator-invalidation 它列出了標準C++容器,以及迭代器失效或仍然有效的情況。 (它回答你的要點3.和4.) – 2013-04-23 17:08:45

+0

關於#4:使用'std :: list' – TemplateRex 2013-04-23 18:02:30

回答

12

這是無效的代碼。標準對序列容器狀態([email protected])的操作定義:

a.insert(p,i,j) - [...] pre:i和j不是迭代器到a中。

因此,您的代碼調用未定義的行爲,因爲它違反了insert操作的前提條件。

如果不是使用insert,你寫一個循環從myvector.rbegin() + 1迭代到myvector.rend() -1和所有的值稱爲push_back,你的代碼是有效的:這是因爲,如果需要重新分配push_back僅無效矢量迭代器和您的來電reserve確保不是這種情況。

一般來說,雖然有些情況下在迭代時修改容器是沒有問題的(例如上面描述的循環),但您必須確保迭代器在這樣做時不會失效。發生這種情況時,每個容器都是特定的。

+0

對於容器特定的迭代器驗證規則請參閱此問題(http://stackoverflow.com/questions/6438086/iterator -invalidation-rules?lq = 1) – TemplateRex 2013-04-23 18:01:59

+0

感謝您的回答。太糟糕了,但似乎工作。我將它添加到我討厭C++的東西列表中。 – tobsen 2013-04-24 10:59:50

相關問題