2016-05-03 8 views
0

Ich habe Code geschrieben, um die Kapazität einer Vorlagen-Containerklasse zu verringern. Nachdem ein Element aus dem Container entfernt wurde, prüft die Löschfunktion, ob 25% des gesamten Speicherplatzes belegt sind und ob eine Reduzierung der Kapazität um die Hälfte dazu führt, dass sie weniger als die von mir festgelegte Standardgröße beträgt. Wenn diese beiden Wahr zurückgegeben werden, wird die Downsize-Funktion ausgeführt. Wenn dies jedoch geschieht, während ich mich in der Mitte einer Const_iterator-Schleife befinde, bekomme ich einen Segfault.Container-Vorlagenklasse - abnehmende Behältergröße

bearbeitet wieder: Ich denke, es ist, weil die const_iterator Zeiger auf das alte Array zeigen, und muss auf den neuen von downsize() erstellt, auf dem sein ... nun, wie das zu tun gehen ...

template <class T> 
void sorted<T>::downsize(){ 

    // Run the same process as resize, except 
    // in reverse (sort of). 
    int newCapacity = (m_capacity/2); 
    T *temp_array = new T[newCapacity]; 

    for (int i = 0; i < m_size; i++) 
    temp_array[i] = m_data[i]; 

    // Frees memory, points m_data at the 
    // new, smaller array, sets the capacity 
    // to the proper (lower) value. 
    delete [] m_data; 
    m_data = temp_array; 
    setCap(newCapacity); 
    cout << "Decreased array capacity to " << newCapacity << "." << endl; 
} 


// Implementation of the const_iterator erase method. 
template <class T> 
typename sorted<T>::const_iterator sorted<T>::erase(const_iterator itr){ 

    // This section is reused from game.cpp, a file provided in the 
    // Cruno project. It handles erasing the element pointed to 
    // by the constant iterator. 
    T *end = &m_data[m_capacity]; // one past the end of data 
    T *ptr = itr.m_current;  // element to erase 

    // to erase element at ptr, shift elements from ptr+1 to 
    // the end of the array down one position 
    while (ptr+1 != end) { 
    *ptr = *(ptr+1); 
    ptr++; 
    } 

    m_size--; 

    // Once the element is removed, check to 
    // see if a size reduction of the array is 
    // necessary. 
    // Initialized some new values here to make 
    // sure downsize only runs when the correct 
    // conditions are met. 
    double capCheck = m_capacity; 
    double sizeCheck = m_size; 
    double usedCheck = (sizeCheck/capCheck); 
    int boundCheck = (m_capacity/2); 
    if ((usedCheck <= ONE_FOURTH) && (boundCheck >= DEFAULT_SIZE)) 
    downsize(); 

    return itr; 
} 


// Chunk from main that erases. 
int i = 0; 
for (itr = x.begin(); itr != x.end(); itr++) { 
    if (i < 7) x.erase(itr); 
    i++; 
} 

Antwort

0

Um Probleme mit für ungültig erklären Iteratoren während einer Löschschleife zu verhindern, können Sie verwenden:

x.erase(itr++); 

statt separaten Schritt und Schritt Anrufe (natürlich, wenn Sie das Löschen über nicht alles, was Sie Schleife würden Sie brauche einen anderen Fall, um die nicht gelöschten Objekte zu erhöhen.) Anmerkung th Dies ist ein Fall, in dem Sie Post-Inkrement statt Pre-Inkrement verwenden müssen.

Das Ganze sieht ein bisschen ineffizient, obwohl. Die Art, wie Sie in ein Array konvertieren, legt nahe, dass es nur mit bestimmten Containertypen funktioniert. Wenn Sie erwarten, dass in der Mitte des Containers viel gelöscht wird, können Sie das Speicherproblem vermeiden, indem Sie einfach einen anderen Container auswählen. Liste vielleicht.

Wenn Sie Vektor wählen, können Sie finden, dass Aufruf shrink_to_fit ist, was Sie wollen.

Beachten Sie auch, dass Erase einen Rückgabewert hat, der auf die (neue) Position des Elements nach dem gelöschten verweist.

Wenn Sie die Zeile zum Zurückgeben eines Iterators an eine neu erstellte, heruntergesetzte Version des Containers verwenden, beachten Sie, dass der Iterator end() nicht mit dem Originalcontainer verglichen werden würde.

+0

Ich habe leider keine große Auswahl, was für ein Container es ist. Es ist für ein Schulprojekt, also haben sie mir diese lange Liste von Methoden/Datenmitgliedern gegeben und gesagt, mach es so umzusetzen. – swingonaspiral

-1

Ich habe das segfault Problem herausgefunden!

Was war los, dass meine x.end() die Größe des Arrays (nicht die Kapazität) verwendet, wobei die Größe ist die Anzahl der Datenelemente im Array gespeichert, anstelle der Kapazität, die tatsächlich ist die Größe des Arrays. Als es nach dem Ende des Arrays suchte, betrachtete es es als zahlreiche Elemente vor dem eigentlichen Ende.

Jetzt zu mehr interessanten Problemen!