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

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

Шрифт:

// память/слоты

// для новых элементов (текущая память)

public:

// ...

};

Эту ситуацию можно изобразить графически.

Поскольку нумерация элементов начинается с нуля, мы показываем, что переменная

sz
(количество элементов) ссылается на ячейку, находящуюся за последним элементом, а переменная
space
ссылается на ячейку, расположенную за последним слотом. Им соответствуют указатели, установленные на ячейки
elem+sz
и
elem+space
.

Когда вектор создается впервые, переменная

space
равна
sz
, т.е. “свободного места” нет.

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

space==sz
. Благодаря этому, используя функцию
push_back
, мы не выходим за пределы памяти.

Конструктор по умолчанию (создающий объект класса

vector
без элементов) устанавливает все три члена класса равными нулю.

vector::vector:sz(0),elem(0),space(0) { }

Эта ситуация выглядит следующим образом:

“Запредельный элемент” является лишь умозрительным. Конструктор по умолчанию не выделяет свободной памяти и занимает минимальный объем (см. упр. 16). Наш класс

vector
иллюстрирует прием, который можно использовать для реализации стандартного вектора (и других структур данных), но стандартные библиотечные реализации отличаются большим разнообразием, поэтому вполне возможно, что в вашей системе класс
std::vector
использует другие стратегии.

19.2.2. Функции reserve и capacity

Самой главной операцией при изменении размера контейнера (т.е. при изменении количества элементов) является функция

vector::reserve
. Она добавляет память для новых элементов.

void vector::reserve(int newalloc)

{

if (newalloc<=space) return; // размер не уменьшается

double* p = new double[newalloc]; // выделяем новую память

for (int i=0; i<sz; ++i) p[i] = elem[i]; // копируем старые

// элементы

delete[] elem; // освобождаем старую память

elem = p;

space = newalloc;

}

Обратите внимание на то, что мы не инициализировали элементы в выделенной памяти. Мы просто резервируем память, а как ее использовать — задача функций

push_back
и
resize
.

Очевидно, что пользователя может интересовать размер доступной свободной памяти в объекте класса

vector
, поэтому, аналогично стандартному классу, мы предусмотрели функцию-член, выдающую эту информацию.

int vector::capacity const { return space; }

Иначе говоря, для объекта класса

vector
с именем
v
выражение
v.capacity–v.size
возвращает количество элементов, которое можно записать в объект
v
с помощью функции
push_back
без выделения дополнительной памяти.

19.2.3. Функция resize

Имея функцию

reserve
, реализовать функцию
resize
для класса
vector
не представляет труда. Необходимо предусмотреть несколько вариантов.

• Новый размер больше ранее выделенной памяти.

• Новый размер больше прежнего, но меньше или равен ранее выделенной памяти.

• Новый размер равен старому.

• Новый размер меньше прежнего.

Посмотрим, что у нас получилось.

void vector::resize(int newsize)

// создаем вектор, содержащий newsize элементов

// инициализируем каждый элемент значением 0.0 по умолчанию

{

reserve(newsize);

for (int i=sz; i<newsize; ++i) elem[i] = 0; // инициализируем

// новые элементы

sz = newsize;

}

Основная работа с памятью поручена функции

reserve
. Цикл инициализирует новые элементы (если они есть).

  • Читать дальше
  • 1
  • ...
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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