容器模板类 - 减少容器大小

时间:2016-05-03 14:56:47

标签: templates segmentation-fault const-iterator

我已经编写了一些代码来减少模板化容器类的容量。从容器中删除元素后,擦除功能会检查是否有25%的空间正在使用中,并且是否将容量减少一半会导致它小于默认大小I' ve组。如果这两个返回true,则缩小函数运行。但是,如果在我在const_iterator循环中间发生这种情况时,我会遇到段错误。

再次编辑:我正在思考它,因为const_iterator指针指向旧数组,需要指向由reduceize()创建的新数组...现在该如何去做该...

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++;   
}

2 个答案:

答案 0 :(得分:0)

为了防止在擦除循环期间使用无效迭代器的问题,您可以使用:

x.erase(itr++);

而不是单独的递增和递增调用(显然,如果你没有删除你循环的所有内容,你需要一个else情况来增加超过未擦除的项目。)注意这是你需要使用post的情况 - 增量而不是预增量。

尽管如此,整个事情看起来有点低效。转换为数组的方式表明它只能用于某些容器类型。如果您希望从容器中间擦除大量内容,则可以通过选择不同的容器来避免内存问题;列表也许。

如果您选择矢量,您可能会发现调用shrink_to_fit就是您想要的。

另请注意,erase的返回值将指向删除后元素的(新)位置。

如果沿着将迭代器返回到新创建的小型容器版本的行,请注意,与原始容器end()迭代器进行比较将不起作用。

答案 1 :(得分:-1)

我发现了段错误问题!

发生的事情是我的x.end()使用了数组的大小(不是容量),其中size是存储在数组中的数据元素的数量,而不是实际的容量数组的大小。因此,当它在寻找数组的末尾时,它在实际结束之前将其视为众多元素。

现在谈谈更多有趣的问题!