Программирование >>  Операторы преобразования типа 

1 ... 44 45 46 [ 47 ] 48 49 50 ... 239


Чтобы предотвратить перераспределение памяти, можно заранее зарезервировать некоторую емкость функцией reserve(). Тем самым гарантируется, что ссылки останутся действительными, пока зарезервированная емкость ие будет исчерпана:

std::vector<1nt> v; Создание пустого вектора v.reserveCSO); Резервирование памяти для 80 элементов

В другом варианте вектор инициализируется достаточным количеством элементов, для чего конструктору передаются дополнительные аргументы. Например, если передать числовое значение, оно интерпретируется как начальный размер вектора:

std::vector<T> v{5); Создание вектора и его инициализация

пятью значениями (с пятикратным вызовом конструктора по умолчанию типа Т)

Конечно, для этого при определении типа элементов должен быть определен конструктор по умолчанию. Но учтите, что для сложных типов даже при наличии конструктора по умолчанию инициализация требует времени. Если элементы инициализируются только для того, чтобы зарезервировать память, лучше воспользоваться функцией reserveQ.

Концепция емкости векторов сходна с аналогичной концепцией для строк (см. с. 468), но с одним существенным различием: в отличие от строк функция reserveO пе может вызываться для уменьшенрш емкости векторов. Вызов reserve() с аргументом, меньшим текущей емкости вектора, игнорируется. Более того, способы оптимизации по скорости и затратам памяти определяются реализацией. Это означает, что реализация может увеличивать емкость с большими приращениями. Для предотвращения внутренней фрагментации многие реа.;тизации выделяют полный блок памяти (около 2 Кбайт) при первой вставке, если ранее не вызывалась функция reserve(). Если программа работает с мтгожеством векторов, содержащих малое количество элементов, такая стратегия приводит к неэффективному расходованию памяти.

Емкость вектора напрямую никогда не уменьшается, поэтому ссылки, указатели и итераторы заведомо остаются действительными даже при удалении элементов (при условии, что они ссылаются на позицию, расположенную перед модифицированными элементами). Однако вставка может привести к тому, что ссылки, указатели и итераторы станут недействительными.

Впрочем, способ косвенного уменьшения емкости вектора все же существует: если поменять местами содержимое двух векторов функцией swap(), при этом также поменяются их емкости. Следующая функция уменьшает емкость вектора с сохранением элементов:

template <class Т>

void shr1nkCapdcity(std::vector<T>& v) {

std::vector<T> tmpCv); Копирование элементов в новый вектор



v.swap(tmp): Перестановка внутренних данных векторов

Емкость вектора можно уменьшить даже без вызова этой функции, просто выполнив следующую команду;

Уменьшение емкости вектора v аля типа Т std::vector<T>Cv).swap(v);

Но не следует забывать, что после вызова функции swap() все ссылки, указатели и итераторы переключаются на новый контейнер. Они продолжают ссылаться па те элементы, на которые они ссылались первоначально. Значит, после вызова функции shrinkCapacity() вес ссылки, указатели и итераторы становятся недействительными.

Операции над векторами Операции создания, копирования и уничтожения

в табл. 6.2 перечислены конструкторы и деструктор векторов. Векторы создаются с инициализацией элементов или без нее. Если передается только размер, элементы создаются конструктором по умолчанию. Обратите внимание: явный вызов конструктора по умолчанию татсже инициализирует базовые типы (в частности, int) нулями; эта особенность языка описана на с. 30. Некоторые из возможных источников инициализации упоминаются на с. 154.

Таблица 6.2. Конструкторы и деструкторы векторов Операция Описание

vector<Elem> с Создает пустой вектор, не содержащий ни одного элемента

vector<Elem> с1(с2) Создает копию другого вектора того же типа (с копированием

всех элементов)

vector<Elem> с{п) Создает вектор из п элементов, создаваемых конструктором

по умолчанию

vector<Elem> cCn,elem) Создает вектор, инициализируемый п копиями элемента elem vector<Elem> c(beg, end) Создает вектор, инициализируемый элементами интервала [beg,end) c.~vector<Elem>() Уничтожает все элементы и освобождает память

Немодифицирующие операции над векторами

в табл. 6.3 перечислены все операции, выполняемые без модификации вектора. Дополнительные замечания приведены на с. 154 и 157.

Компилятор может посчитать эту команду неправильной, потому что в ней аекои-стантная функция класса вызывается для времептюго значения. Однако па самом деле стандарт С++ позволяет вызывать неконстантные функции классов для временных значений.



Таблица 6.3. Немодифицирующие операции над векторами

Операция Описание

csizef) c.emptyO

c.max sizeO capacityO

reserveO cl == c2 cl! = c2 cl < c2 cl > c2 cl <= c2 cl >= c2

Возвращает фактическое количество элементов

Проверяет пуст ли контейнер (эквивалент size()==0, но иногда выполняется быстрее)

Возвращает максимально возможное количество элементов

Возвращает максимально возможное количество элементов без перераспределения памяти

Увеличивает емкость вектора, если текущая емкость меньше заданной Проверяет равенство с1 и с2

Проверяет неравенство с1 и с2 (эквивалент !(с1==с2)) Проверяет, что с1 меньше с2 Проверяет, что с1 больше с2 (эквивалент с2<с1) Проверяет, что с1 не больше с2 (эквивалент !(с2<с1)) Проверяет, что с1 не меньше с2 (эквивалент !(с1<с2))

Присваивание

в табл. 6.4 перечислены операции присваивания новых элементов с одновременным удалением старых. Набор функций assign() соответствует набору конструкторов класса. При присваивании могут использоваться разные источники (контейнеры, массивы, стандартный входной поток данных) - по аналогии с источниками, используемыми при вызове конструкторов (см. с. 154).

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

Операция

Описание

с1 = с2

Присваивает cl все элементы с2

c.assign(n,elem)

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

c.assign(beg,end)

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

cl.5v/ap(c2)

Меняет местами содержимое с1 и с2

swap(cl,c2)

То же, но в форме глобальной функции

Все операции присваивания вызывают конструктор по умолчанию, копирующий конструктор, оператор присваивания и/или деструктор типа элемента в зависимости от того, как изменяется количество элементов в контейнере. Пример:

std::list<Elem> 1; std::vector<Elem> coll:

Функция reserveO изменяет вектор, поскольку в результате ее выполнения становятся недействительными ссылки, указатели и итераторы. Тем пс менее она включена в таблицу, потому что вызов reserveO пе .меняет логаческого содержимого контейнера.



1 ... 44 45 46 [ 47 ] 48 49 50 ... 239

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика