2011-12-06 107 views
2

我迷路了:除非函數調用(Z_UB-> set())在++之前,std :: string向量的迭代器才能完美工作。下面的代碼:C++迭代器隨機失效

std::vector<std::string>::iterator it = g_SPP.scenarios->getVector().begin(); 
std::cout << "begin of vector: " << *it << std::endl; 
Z_UB->set("s1", "scn2", 350); 
it++; 
std::cout << "second of vector: " << *it << std::endl; 

創建以下輸出

begin of vector: scn1 

但是,如果我將函數調用是這樣的:

std::vector<std::string>::iterator it = g_SPP.scenarios->getVector().begin(); 
std::cout << "begin of vector: " << *it << std::endl; 
it++; 
std::cout << "second of vector: " << *it << std::endl; 
Z_UB->set("s1", "scn2", 350); 

結果如下,這是預期行爲:

begin of vector: scn1 
second of vector: scn2 

裏面的Z_UB-> set()函數沒有什麼離開,但調用本身:

void Parameter::set(std::string _i, std::string _j, float value) { 
//int i = indexSets[0]->backIndex(_i); 
//int j = indexSets[1]->backIndex(_j); 

//data2D[0][0] = value; 
} 

所以,如果我叫Z_UB->設置()函數,我創建迭代器後,訪問它會使程序崩潰。我錯過了關於迭代器的事情嗎?

+2

這裏沒有足夠的信息來診斷您的具體問題。迭代器不會「隨機地」失效,所以問題出現在你的代碼中,但是在你的代碼中這個帖子裏並不清楚問題所在。 'Z_UB'確實是'Parameter'類型的嗎?還有其他什麼類型的,可以修改底層'vector'的東西嗎?在向量的內部存儲器的大小調整過程中,矢量迭代器無效。 – Chad

+1

getVector()是否返回對矢量或副本的引用? –

+0

它返回的矢量副本(根據我沒有使用&任何地方) – buhmann

回答

1

.getVector()返回了一個向量的副本。將迭代器與完全不同對象的迭代器的終點進行比較沒有任何意義。返回參考解決了問題。

@Xeo還指出了一個更好的解釋:當從一個副本像這樣創建一個迭代器:

std::vector<std::string>::iterator it = g_SPP.scenarios->getVector().begin(); 

副本立即被破壞從而無效剛纔創建的迭代器。所以迭代器不應該首先返回第一個元素,但我只能猜測這在編譯器的實現中深藏不露。

+1

這也是,返回的副本在創建迭代器的行的末尾立即銷燬,因爲迭代器立即失效並且您進入了未定義行爲的區域。 – Xeo

1

a std::vector<T>::iterator將在迭代時添加或刪除元素時失效,如果向量需要在內部調整自身大小時添加元素。

+0

從示例代碼這不是發生在這裏... – Benoit

2

如果g_SPPglobal變量,那麼它上面的迭代器將被任何變異操作無效化。


更新 - 這是自1998年ISO/ANSI規格:

下如果需要分配所有無效引用,迭代器和指針指的是序列的元素。如果當前的capacity()小於目標矢量大小,則需要分配。

  • void reserve(size_type n)
  • iterator insert(iterator position, const T& x)
  • void insert(iterator position, size_type n, const T& x)
  • void insert(iterator position, InputIterator first, InputIterator last),和

擦除無效的所有參考文獻,迭代器和指針指的是初始擦除元件的位置後的元件。

  • iterator erase(iterator position)
  • iterator erase(iterator first, iterator second)

調整大小的向量等同於調用任一inserterase。根據23.2.4。2/6:resize(sz, c=value_type())具有相同的效果:

if (sz > size()) 
    insert(end(), sz - size(), c); 
else if (sz < size()) 
    erase(begin() + sz, end()); 
else 
    ; 
+0

有趣的是,你可以添加一個參考支持這個請嗎? – Benoit

+0

通過變異你是指只添加和刪除元素嗎? –

2

幾種可能性:

  • 要麼你沒有一個很好的reproductible例子:也許在你第一次運行在您的向量只有一個元素(它是如何填充的?),並調用未定義的行爲,因爲您沒有檢查it針對g_SPP.scenarios->getVector().end()
  • Z_UB->set不符合您的想法。它是一個多態類嗎? set是虛擬的嗎? ->運算符是否超載?
  • 您的應用程序是多線程的,而另一個線程正在改變您的容器?
+0

- > set函數被重載,但我添加了一些調試輸出到所有其他版本。只有我希望運行的那個被調用。 – buhmann