2017-03-06 5 views
-2

Ich habe kleines Stück Code, der einen Vektor der Klasse (Vector2) für 2-dimensionale Vertices und einen Vektor der Template-Klasse DynamicLine enthält, die Vector2-Objekt für Argument verwendet.Warum werden meine Zeiger ungültig, wenn ich vector.reserve() nicht verwende?

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; 

      } 

Problem ist das nächste. Zum Beispiel, wenn ich zwei Eckpunkte und eine Linie zwischen ihnen hinzufügen, dann funktioniert alles gut. Aber wenn ich jetzt einen anderen Eckpunkt (m_coords.push_back (Vector2 (event-> x(), event-> y())) hinzufügen), dann werden die Zeile dedaperas und Werte in m_lines Vektor in sehr zufällige große Zahlen geändert. Ich habe gelesen, dass Zeiger ungültig werden. Wenn Sie neue Werte in den Vektor schieben, werden einige schließlich erweitert. Ich habe auch mein Problem mit vector :: reserve behoben, aber da ich mir sicher bin, dass ich das nicht richtig mache, könnte mir bitte jemand erklären, wie ich vector :: reserve verwenden soll und warum ich das tun muss?

+2

1) Fixieren Sie Ihre Einrückung. 2) Erstelle [mcve]. 3) Versuchen Sie, den Debugger zu verwenden, um durch Ihren Code zu gehen, während Sie die Werte der Variablen bei jedem Schritt prüfen. In dieser Reihenfolge. –

Antwort

1

Ich habe Ihren Code nicht genau angeschaut, aber es scheint, als wäre es die Neuzuweisung des Vektors, die Ihnen Probleme bereitet.

Ein Vektor verfolgt immer zwei Größen: seine Kapazität und die Anzahl der darin enthaltenen Objekte. Wenn Sie eine push_back ausführen und die Kapazität bereits auf dem Maximum ist, kopiert sie sich an einen anderen Speicherort im Speicher mit mehr Speicherplatz und einer größeren Kapazität. Ihre Zeiger zeigen wahrscheinlich immer noch auf den ursprünglichen Speicherort.

Wenn Sie mit Vektoren arbeiten, ist es möglicherweise besser, Indizes anstelle von Zeigern zu behalten.

EDIT: Iterieren Sie über ein Array, auf dem Sie einfügen Operationen ausführen können. Das sollte nicht sein.

1

Es ist ziemlich einfach. Wenn Sie push_back und vector nicht genug capacity haben, muss es mehr Speicher zuweisen und Ihre Elemente an den neuen Speicherort kopieren (oder verschieben). Dies macht alle Iteratoren/Zeiger ungültig, die auf die alten Elemente zeigen (sie zeigen jetzt nur auf den alten freigegebenen Speicherblock), was bedeutet, dass sie im Grunde auf Müll zeigen - also müssen Sie neue Iteratoren nach dem push_back bekommen.

reserve Aufruf teilt der Vektor einen Speicherblock up-front zu vergeben, so dass jede nachfolgendenpush_back kann garantiert werden, um nicht eine Umverteilung müssen (wenn Sie in der Reservierung Aufenthalt (eigentlich capacity)) und wird somit nicht Iteratoren/Zeiger auf Elemente ungültig machen.

Verwandte Themen