Вход/Регистрация
Программирование. Принципы и практика использования C++ Исправленное издание
вернуться

Страуструп Бьерн

Шрифт:

}

Аналогично можно написать функцию

vector<T,A>::resize
.

template<class T, class A>

void vector<T,A>::resize(int newsize, T val = T)

{

reserve(newsize);

for (int i=sz; i<newsize; ++i) alloc.construct(&elem[i],val);

// создаем

for (int i = newsize; i<sz; ++i) alloc.destroy(&elem[i]);

// уничтожаем

sz = newsize;

}

Обратите внимание на то, что, поскольку некоторые типы не имеют конструкторов по умолчанию, мы снова предоставили возможность задавать начальное значение для новых элементов.

Другое новшество — деструктор избыточных элементов при уменьшении вектора. Представьте себе деструктор, превращающий объект определенного типа в простой набор ячеек памяти.

“Непринужденное обращение с распределителями памяти” — это довольно сложное и хитроумное искусство. Не старайтесь злоупотреблять им, пока не почувствуете, что стали экспертом.

19.4. Проверка диапазона и исключения

Мы проанализировали текущее состояние нашего класса

vector
и обнаружили (с ужасом?), что в нем не предусмотрена проверка выхода за пределы допустимого диапазона. Реализация оператора
operator[]
не вызывает затруднений.

template<class T, class A> T& vector<T,A>::operator[](int n)

{

return elem[n];

}

Рассмотрим следующий пример:

vector<int> v(100);

v[–200] = v[200]; // Ой!

int i;

cin>>i;

v[i] = 999; // повреждение произвольной ячейки памяти

Этот код компилируется и выполняется, обращаясь к памяти, не принадлежащей нашему объекту класса

vector
. Это может создать большие неприятности! В реальной программе такой код неприемлем. Попробуем улучшить наш класс
vector
, чтобы решить эту проблему. Простейший способ — добавить в класс операцию проверки доступа с именем
at
.

struct out_of_range { /* ... */ }; // класс, сообщающий об ошибках,

// связанных с выходом за пределы допустимого диапазона

template<class T, class A = allocator<T> > class vector {

// ...

T& at(int n); // доступ с проверкой

const T& at(int n) const; // доступ с проверкой

T& operator[](int n); // доступ без проверки

const T& operator[](int n) const; // доступ без проверки

// ...

};

template<class T, class A > T& vector<T,A>::at(int n)

{

if (n<0 || sz<=n) throw out_of_range;

return elem[n];

}

template<class T, class A > T& vector<T,A>::operator[](int n)

// как прежде

{

return elem[n];

}

Итак, мы можем написать следующую функцию:

void print_some(vector<int>& v)

{

int i = –1;

cin >> i;

while(i!= –1) try {

cout << "v[" << i << "]==" << v.at(i) << "\n";

}

catch(out_of_range) {

cout << "Неправильный индекс: " << i << "\n";

}

}

Здесь мы используем функцию

at
, чтобы обеспечить доступ к элементам с проверкой выхода за пределы допустимого диапазона, и генерируем исключение
out_of_range
, если обнаруживаем недопустимое обращение к элементу вектора.

Основная идея заключается в использовании операции индексирования

[]
, если нам известно, что индекс правильный, и функции
at
, если возможен выход за пределы допустимого диапазона.

  • Читать дальше
  • 1
  • ...
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: