Ответ в теме: Реализовать класс одномерного массива

      Комментарии к записи Ответ в теме: Реализовать класс одномерного массива отключены

Главная Форумы Программирование Программирование на С++ Реализовать класс одномерного массива Ответ в теме: Реализовать класс одномерного массива

#2860

Конструктор класса вызывает malloc чтобы выделить память. Если при этом он получить NULL – значит нужный блок памяти выделить не удалось, поэтому вырабатывается исключение:

template <class ElementType>
Array<Elementtype>::Array() : m_realSize(Step), m_size(0), m_array(0) { 
  m_array = (ElementType*)malloc(sizeof(ElementType)*m_realSize);
  if (0 == m_array) {
    throw bad_allocation();
  }
}

Вырабатывать исключения в конструкторе иногда опасно, однако в этом случае это допустимо, т.к. стандарт языка гарантирует при этом корректное освобождение памяти из под членов класса, созданных на стеке (m_realSize, m_size и указатель m_array). Утечки памяти, выделенной динамически (вызовом malloc) также не произойдет – ведь мы вырабатываем исключение только если память не удалось выделить. Подробнее: “Обработка исключений в конструкторе“.

Деструктор убеждается что массив был создан (указатель не равен нулю) и освобождает память:

template <class ElementType>
Array<Elementtype>::~Array()  { 
  if (m_array)
    free(m_array);
} 

Строго говоря, в этом коде можно обойтись без проверки указателя, т.к. если мы добрались до деструктора, то паять однозначно была успешно выделена.

Функции получения элементов и параметров массива:

template <class ElementType>
ElementType* Array<elementtype>::get() { 
  return m_array; 
} 

template <class ElementType>
unsigned int Array<elementtype>::size() { 
  return m_size;  
} 
 
template <class ElementType>
ElementType& Array<Elementtype>::operator [] (unsigned int index) { 
  if (index < 0 || index > m_size)
    throw bad_index();
  return m_array[index];
}

Наибольший интерес может представлять функция добавления элемента, т.к. она содержит код увеличения размера массива с помощью realloc:

template <class ElementType>
void Array<Elementtype>::push_back(const ElementType &item) { 
  if (++m_size > m_realSize) { 
    m_realSize += Step;
    
    ElementType *biggest_array;
    biggest_array = (ElementType *)realloc(m_array, sizeof(ElementType)*m_realSize);
 
    if (biggest_array == NULL) 
      throw bad_allocation();
    
    m_array = biggest_array;
  } 
 
  m_array[m_size-1] = item;
}

В случае ошибки выделения памяти функция realloc вернет нулевой указатель, а начиная с С++11 она не освобождает память по принятому указателю. Поэтому нельзя обойтись без вспомогательного указателя, в который требуется сохранить результат. Только в случае успешного выделения памяти содержимое m_array обновляется, в противном случае бросается исключение и память из под массива будет освобождена в деструкторе.

Проверить работу функции можно следующим кодом:

int main() { 
  Array<int> m_array;

  for(unsigned int i = 0; i < 15; i++) 
    m_array.push_back(rand() % 100);
  

  for(unsigned int i = 0; i < m_array.size(); i++) 
    cout << m_array[i] << " ";
  
  cout << endl;
  
  for(unsigned int i = 0; i < m_array.size(); i++) 
    m_array[i] = i;
  
  for(unsigned int i = 0; i < m_array.size(); i++) 
    cout << m_array[i] << " ";

  cout << endl; 
}

Вложения: