[英]In C++, Debug assertion failed window pops up & I get vector iterators incompatible error runtime
[英]Debug Assertion : Vector iterators incompatible (C++)
for (int i = 0; i < m_pGameField->dimensions()->first; i++)
{
for (int j = 0; j < m_pGameField->dimensions()->second; j++)
{
for (std::vector<std::shared_ptr<GameGridElement>>::iterator it = m_pGameField->getField(i, j)->getElements().begin();it != m_pGameField->getField(i, j)->getElements().end(); ++it)
{
if ((*it)->getName().compare("Spawn") == 0)
{
tmpSpawns.push_back(std::static_pointer_cast<SpawnElement>((*it)));
}
}
}
}
大家好,我在上層代碼方面遇到了一些問題。 該代碼段應能找到2d游戲場中的所有生成物。 當它出現在第三個迭代的開頭時,它會發出Debug斷言錯誤,並顯示以下消息:“ Vector迭代器不兼容。現在這是崩潰之前的一步。我從Visual Studio調試器中獲取了它們:
getElements()返回了{size = 0}; i = 0; j = 0; begin()返回null的struct。 它是NULL結構
我看到向量為空,但是不應該由it!= end()部分處理嗎?
您尚未發布足夠的代碼來確定,但是以下猜測應該是正確的:
getElements()
最有可能通過值而不是通過引用返回。
例如:
std::vector<std::shared_ptr<GameGridElement>> Field::getElements()
{
// ...
return result;
}
這將返回副本 ! 這意味着每次調用getElements
,都會得到一個不同的向量。
對於編譯器,這沒有任何區別。 類型安全性對您沒有幫助,因為std::vector<std::shared_ptr<GameGridElement>>::iterator
是std::vector<std::shared_ptr<GameGridElement>>::iterator
, 即使您有兩個迭代器屬於不同的容器實例 。 它們具有相同的類型,因此代碼可以編譯。
但是,在運行時,可以進行其他檢查以確保正在比較的兩個迭代器確實屬於同一容器對象。 這將看似隨機的“奇怪”行為或虛假崩潰轉變為確定的保證崩潰,以立即告訴您必須修復某些問題。
再次考慮以下這一行:
for (
std::vector<std::shared_ptr<GameGridElement>>::iterator
it = m_pGameField->getField(i, j)->getElements().begin();
it != m_pGameField->getField(i, j)->getElements().end();
++it
)
it
被初始化為getElements().begin()
,然后由!=
與getElements().end()
。 但是如上所述,每個getElements()
返回一個不同的向量,因此您獲得了不兼容的迭代器。
這是解決問題的簡單方法:
std::vector<std::shared_ptr<GameGridElement>> elements =
m_pGameField->getField(i, j)->getElements();
for (std::vector<std::shared_ptr<GameGridElement>>::iterator it = elements.begin();
it != elements.end(); ++it)
這樣可以確保begin()
和end()
將迭代器返回到相同的容器實例。
作為參考,下面是一段簡單的代碼來重現該行為:
#include <vector>
int main()
{
std::vector<int> v1;
std::vector<int> v2;
bool b = v1.begin() == v2.begin();
}
請注意,C ++標准沒有在運行時強制進行迭代器兼容性檢查。 您的編譯器必須提供它們,並且您必須使用正確的編譯器選項來啟用它們,或者在不需要或負擔不起它們時禁用它們。
順便說一句,如果您可以使用C ++ 11,則可以使用基於范圍的for
循環不僅可以修復錯誤,還可以使代碼更加簡潔。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.