Информатика: Методические указания к лабораторным работам № 1-5. Функции. Обработка символьных данных. Организация работы с файлами, страница 10

Функция reserve( n) устанавливает минимальную емкость контейнера равной n при условии, что n не меньше текущего размера. Таким образом, для предотвращения лишних затрат следует установить достаточно большую емкость контейнера функцией reserve, причем сделать это нужно как можно раньше – желательно сразу же после конструирования контейнера.

Чтобы разобраться с этими тонкостями, рассмотрим пример (пример 3).

Пример 3

vector<int> v; // Создаем пустой вектор

cout<<"Пустой вектор"<<endl;

cout<<"Емкость вектора "<<v.capacity()<<"\nКоличество элементов"

<<v.size()<<endl;

ints = 0;

// Заполняем вектор

for (int i=1; i<=1000; ++i)

 if(v.size()==v.capacity()) s++;

v.push_back(i);}

cout<<"\nПосле заполнения вектора"<<endl;

cout<<"Емкость вектора "<<v.capacity()<<"\nКоличество элементов" <<v.size()<<endl;

cout<<"Число перерасределения памяти = "<<s<<endl;

cout<<"\nДобавим в конец вектора еще 67 элементов"<<endl;

v.insert(v.end(),67,1);

cout<<"Емкость вектора "<<v.capacity()<<"\nКоличество элементов" <<v.size()<<endl;

Результат

Пустой вектор

Емкость вектора 0

Количество элементов 0

После заполнения вектора

Емкость вектора 1066

Количество элементов 1000

Число перераспределений памяти 18

Добавим в конец вектора еще 67 элементов

Емкость вектора 1599

Количество элементов 1067

Анализ

Как и ожидалось, в пустом векторе число элементов, как и его размер, равны нулю. В процессе заполнения вектора 18 раз произошло перераспределение памяти, т. е. 18 раз происходила процедура, опи-санная выше. В результате размер (емкость) вектора превысил коли-чество элементов в нем на 66 элементов. Предположим, что нам нужно добавить в вектор еще 67 элементов, т. е. необходимое количество элементов в векторе превышает его текущий объем всего на один элемент. В этом случае опять происходит перераспределение памяти и объем памяти увеличивается в 1,5 раза. Таким образом, вместо нужного объема 1067 мы получили 1599.

При известном, количестве элементов вектора возникшие труд-ности (большое количество перераспределений памяти и избыточный размер вектора) можно решить просто:

vector<int> v ;

v.reserve(1067);

Тогда число перераспределений памяти будет равно нулю, а емкость – 1067, т. е. равной количеству элементов. Но ведь вектор – это динамический массив и размеры массива заранее не известны. Тогда можно подстраховаться и зарезервировать заведомо больший размер вектора (например, v.reserve(2000)). А чтобы вектор не удержи-вал ненужную память (2000 – 1067), необходимо сократить емкость от максимальной (2000) до используемой в настоящий момент (1067). Подобное сокращение емкости обычно называется «сжатием по размеру». Это сжатие в векторе v можно выполнить с помощью оператора:

vector<int>(v).swap(v); (табл. 3).

Таблица 3

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

Операция

Описание

v1 = v2

Присваивает v1 все элементы v2

v.assign(n,elem)

Присваивает n копий заданного элемента

v.assign(v1.beg,v1.end)

Присваивает элементы интервала [beg,end)

v1.swap(v2)

Меняет местами содержимое v1 и v2

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

Пример 4

vector<int> v1;
for( int i = 0; i < 10; i++ ) v1.push_back( i ); // Заполнение вектора
vector<int> v2;
// Копирование вектора v1 в вектор v2
v2.assign( v1.begin(), v1.end() );
for( int i = 0; i < v2.size(); i++ ) cout << v2[i] << " ";

Результат

  0  1  2  3  4  5  6  7  8  9

В табл. 4 перечислены все операции прямого обращения к элементам векторов. Как принято в С и C++, первому элементу вектора соответствует индекс 0, а последнему – индекс size()-1. Таким образом, n-му элементу соответствует индекс  n – 1.