2016-05-03 7 views
0

私は、テンプレートコンテナクラスの容量を減らすためにいくつかのコードを書いています。要素がコンテナから削除された後、消去機能は総スペースの25%が使用されているかどうかをチェックし、容量を半分に減らすと設定したデフォルトサイズよりも小さくなるかどうかをチェックします。これらの2つが真である場合、ダウンサイズ機能が実行されます。しかし、私がconst_iteratorループの途中にいるときにこれが発生した場合、私はsegfaultを取得します。コンテナテンプレートクラス - コンテナサイズを小さくする

もう一度編集してください:const_iteratorポインタが古い配列を指していて、downsize()によって作成された新しいポインタを指す必要があるからだと思います...

消去ループ中に無効化されたイテレータの問題を防ぐため
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++; 
} 

答えて

0

、あなたが使用することができます。

x.erase(itr++); 

代わりに別の増加と増加のコール(あなたの上にあなたのループすべてを消去していない明らかならばと思います消去されていない項目を超えて増やすには、別のケースが必要です)。プリインクリメントではなくポストインクリメントを使用する必要がある場合です。

しかし、全体的には少し非効率に見えます。配列に変換する方法は、とにかく特定のコンテナタイプでしか動作しないことを示唆しています。コンテナの中央から多くの消去が行われることが予想される場合は、別のコンテナを選択するだけでメモリの問題を回避できます。おそらくリスト。

vectorを選択すると、shrink_to_fitを呼び出すことが必要な場合があります。

また、消去には、消去された要素の(新しい)位置を示す戻り値があります。

イテレータを新しく作成したダウンサイズのコンテナに戻す行を表示すると、元のコンテナend()イテレータと比較すると機能しません。

+0

私は残念なことに、どのようなコンテナであるかについてはあまり選択肢がありません。それは学校プロジェクトのために、彼らは私にこのメソッド/データメンバーの長いリストを与えて、それがこのように実装すると言いました。 – swingonaspiral

-1

私はsegfaultの問題を理解しました!

x.end()は配列のサイズ(容量ではなく)を使用していました。サイズは実際には容量の代わりに配列に格納されたデータ要素の数です配列のサイズだから、配列の終わりを探していたとき、それは実際の終わりの前にそれを数多くの要素として見ていました。

今、さらに興味深い問題に!

関連する問題