2017-03-06 40 views
-2

我有一小段代碼,它包含一個用於二維頂點的類矢量(Vector2)和一個向Vector2類型對象提供參數的模板類DynamicLine矢量。爲什麼我的指針失效,如果我不使用vector.reserve()?

std::vector<Vector2> m_coords; 
std::vector<DynamicLine<Vector2>> m_lines; 
Vector2 *lineVec = NULL; 





bool draw = true; 
case DrawingWidgetState::ADD_VERTEX_SELECTED:{ 
       for(auto it = m_coords.begin(); it != m_coords.end(); it++) 
        if(it->distanceFrom(Vector2(event->x(), event->y())) < 20 && !m_coords.empty()){ 
         draw = false; 
         break; 
        } 

       if(draw){ 

        if(event->x() < m_mainWindow->width() - 10 && event->x() >= 10 
          && event->y() < m_mainWindow->height() && event->y() >= 10) { 


         m_coords.push_back(Vector2(event->x(), event->y())); 
         update(); 
        } 
       } 
       break; 

      } 


case DrawingWidgetState::ADD_LINE_SELECTED:{ 
       for(auto it = m_coords.begin(); it != m_coords.end(); it++) 
        if(it->distanceFrom(Vector2(event->x(), event->y())) < 10){ 

         if(!i){ 
          lineVec = &(*it); 
          i++; 
         } 

         else{ 

          m_lines.push_back(DynamicLine<Vector2>(lineVec, &(*it))); 
          i = 0; 

         } 
         update(); 
         break; 
        } 
       break; 

      } 

問題是未來。例如,如果我添加兩個頂點和它們之間的一條線,那麼一切正常。但是,如果我現在添加另一個頂點(m_coords.push_back(Vector2(event-> x(),event-> y()));),則線條dissaperas和m_lines矢量中的值將更改爲非常隨機的大數字。我讀了一些關於指針失效的信息。如果你將新的值推向矢量,那麼最終會有一些擴展。我也使用vector :: reserve修復了我的問題,但由於我確定我沒有這樣做,任何人都可以請解釋我應該如何使用vector :: reserve以及爲什麼我需要這樣做?

+2

1)修復你的縮進。 2)創建[mcve]。 3)嘗試使用調試器來遍歷代碼,同時在每個步驟檢查變量的值。以該順序。 –

回答

1

我沒有仔細看過你的代碼,但它好像是重新分配給你造成麻煩的向量。

矢量始終跟蹤兩種尺寸:其容量和其包含的對象數量。如果您執行push_back操作,且其容量已達到最大值,則會將其自身複製到內存中具有更多空間和更大容量的其他位置。你的指針可能仍然指向原始位置。

使用向量時,最好保持索引而不是指針。

編輯:你迭代你可以執行插入操作的數組。這不應該。

1

這很簡單。當你push_backvector沒有足夠的capacity它需要分配更多的內存並將你的元素複製(或移動)到新的位置。這會使任何指向舊元素的迭代器/指針無效(它們現在只是指向舊的釋放內存塊),這意味着它們基本上指向垃圾 - 所以你必須在push_back之後獲得新的迭代器。

調用reserve告訴矢量分配的內存塊的前期,使得任何隨後push_back可以保證不需要重新分配(如果留下的預約(實際上capacity)內),並因此將不無效迭代器/指向元素的指針。

相關問題