Как проверить что вектор пустой c
Перейти к содержимому

Как проверить что вектор пустой c

  • автор:

Как проверить что вектор пустой c

БлогNot. C++: изучаем стандартный контейнер vector

C++: изучаем стандартный контейнер vector

Стандартная библиотека шаблонов STL (Standard Template Library)позволяет создавать списки, векторы, очереди, стеки и т.д. из элементов любых типов данных. Не для всех контейнеров есть готовые шаблоны, скажем, их нет для матрицы, произвольного дерева узлов и т.д. Но в таких случаях можно использовать одни шаблоны для создания других.

Класс vector — самый простой и часто применяемый шаблон стандартной библиотеки STL. По сути, он призван заменить «неуправляемый» (точнее, управляемый программистом) динамический массив. Вектор удобнее, чем обычный динамический массив. Он не ускорит работу вашей программы и не предоставит каких-либо «секретных механизмов» управления оперативной памятью. Он просто возьмёт на себя заботу о своей размерности и предоставит методы для типовых операций с массивами.

Для работы с векторами подключается заголовочный файл vector и стандартное пространство имен:

Пространство имён можно, конечно, и не подключать, но тогда придётся везде писать std::vector вместо vector .

Для начала опишем пустой вектор:

Из описания видно, что мы имеем дело с шаблоном, то есть, вектор можно составлять из элементов любого простого или составного типа. Здесь мы использовали тип элементов int .

Теперь посмотрим, как вектор управляет распределением памяти:

Этим оператором память зарезервирована под 10 элементов, но размерность вектора, возвращаемая методом v.size() , всё равно равна нулю.

Вот теперь размерность вектора действительно равна 10, и метод v.size() вернёт это значение.

Все показанные три действия мы могли выполнить одним оператором:

Здесь произошёл вызов конструктора класса vector , мы которому передали аргумент-размерность, равный 10.

  • переопределенным оператором [] — корректность индекса тогда не контролируется, как и для обычных массивов C/C++;
  • методом at(i) , где i — индекс нужного элемента, при этом, контролируется корректность индекса, и, если нужно, генерируется исключение.

Обработка исключений в простейшем случае делается так:

1. Подключить заголовочный файл <exception> ;

2. «Подозрительный» код, который может привести к ошибке, заключить в блок try («попытаться»):

3. Обработку ошибочных ситуаций вынести в блок catch («перехватить»):

В частности, системное сообщение об ошибке будет возвращаться методом e.what() .

Например, показанный ниже код не сгенерирует исключения (в новых сборках Visual Studio 2019 уже сгенерируется системное исключение):

А вот этот — сгенерирует:

Проверить, пуст ли вектор, можно методом empty :

Как и для динамических массивов, для обработки векторов часто пишут функции. Так как вектор — это шаблонный класс, удобнее в функциях также применять шаблоны. Например, метод печати вектора в консоль может иметь вид:

Это сработает с любым скалярным типом данных, для которого компилятор смог переопределить оператор [] :

Скопировать вектор можно как минимум двумя способами:

1. Вызвать конструктор, которому передать ранее определенный вектор:

2. Скопировать вектор поэлементно в цикле for с помощью оператора [] или метода at , думаю, Вы легко напишете такой код самостоятельно.

Векторы можно сравнивать переопределённым оператором == :

Для добавления элементов сущестует метод insert , имеющий несколько перегрузок:

Здесь мы уже чуть забежали вперёд, потому что метод insert , как и другие методы класса, для перебора элементов контейнера требует определить итератор (аналог указателя для обычных массивов):

Можно вставить значение в вектор и другим методом:

Аналогично обстоит дело с методом erase для удаления элементов и другими методами класса. Более того, многие имена методов применимы и к другим контейнерам STL, а не только к вектору.

Чаще всего для добавления элемента в конец вектора пишут так:

Возможен и вполне традиционный ввод элементов вектора с клавиатуры:

Изучив итераторы и встроенные алгоритмы, мы могли бы выполнить обмен данными с консолью и без «видимых» циклов:

Как и на обычные динамические структуры, на контейнеры можно создавать указатели:

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

Класс vector . Методы, определяющие и изменяющие общие характеристики массива

Метод max_size() позволяет получить максимально-допустимое количество элементов массива. Это значение зависит от типа элементов массива vector. Для различных типов оно разное
В зависимости от типа данных массива vector , это значение может колебаться. Чем больше размер данных каждого элемента массива vector , тем меньше значение max_size() .
Синтаксис объявления метода max_size() следующий:

здесь T – тип элементов динамического массива.

Пример.

3. Метод capacity() . Определить размер массива с учетом зарезервированной памяти

Метод capacity() возвращает количество элементов, выделенное для массива.

При добавлении нового элемента в массив, нужно выделить дополнительную память на 1 элемент больше. Однако, компилятор может увеличить размер памяти на несколько элементов чтобы при последующем добавлении еще одного элемента не выполнять повторно такие операции как освобождение памяти под предварительно созданный массив, выделение нового фрагмента и тому подобное. Таким образом ускоряется быстродействие.

Синтаксис объявления метода следующий

здесь T – тип элементов массива.

Пример. В примере демонстрируется разница между методами size() и capacity() .

Результат выполнения программы

Как видно из результата, при добавлении нового элемента, количество элементов в массиве увеличилась на 1 и составляет 11 (метод size() ). Однако, сам размер массива увеличился на 5 элементов и составляет 15 (метод capacity() ). Теперь можно добавлять еще 4 элемента без лишнего перераспределения памяти. Если добавление элементов будет выполняться в цикле, то такой подход позволит ускорить выполнение программы.

4. Метод empty() . Определить, пустой ли вектор

С помощью метода empty() можно определить, пустой ли массив (количество элементов в массиве равно 0). Общая форма метода empty() следующая:

здесь T – тип элементов массива.

Пример.

Результат выполнения программы

5. Метод shrink_to_fit() . Установить размер массива в памяти по количеству элементов в нем без дополнительного резервирования памяти

Метод shrink_to_fit() позволяет выровнять память, выделенную (зарезервированную) для элементов массива (метод c apacity() ) с памятью, занятой элементами массива (метод size() ).
Количество зарезервированных элементов (для которых выделена память) возвращается методом capacity() . Количество элементов, определенных в массиве, возвращаются методом size() . Значение, возвращаемое методом capacity() всегда больше или равно значения, возвращаемого методом size() .
Если значение, полученное методом capacity() больше значения, полученного методом size() , то метод shrink_to_fit() позволяет выровнять эти значения. При этом уменьшается размер памяти, возвращаемый методом capacity() .
Метод эффективен, когда в результате различных операций с массивом, остается большой избыток зарезервированных элементов в массиве.

Общая форма метода следующая

После вызова этого метода, методы size() и capacity() всегда будут возвращать одинаковые значения.

Пример.

Результат выполнения программы

Как видно из результата, после добавления элемента в массив, размер массива увеличился с 5 до 6. Это естественно и метод size() это показал. Но реальный размер массива увеличился с 5 до 7, о чем показал метод capacity() . То есть, выделилось на 1 элемент больше.
Вызов метода shrink_to_fit() перераспределил память так, что количество выделенной памяти под элементы стала равна количеству памяти, занятой элементами.

6. Метод resize() . Изменить размер массива

Метод resize() позволяет изменять размер динамического массива в большую или в меньшую сторону. Метод имеет две перегруженные реализации.
Первая реализация имеет следующее объявление

  • _NewSize – новый размер массива. Если _NewSize больше текущего размера массива, то все остальные элементы дополняются нулевыми значениями.

Вторая реализация имеет следующее объявление

  • _NewSize – новый размер массива;
  • T – тип элементов массива;
  • Val — значения, которыми дополняются элементы массива в случае, если значение _NewSize больше текущего размера.

Пример.

7. Метод reserve() . Зарезервировать дополнительную память для элементов массива

Метод reserve() позволяет выделить (зарезервировать) память для элементов массива, которая возвращается методом capacity() . Реальное количество элементов в массиве, которое возвращается методом size() , не изменяется.
Правильное использование метода в программе позволяет ускорить выполнение программы в случаях, когда активно изменяется размер массива (часто выполняются операции добавления, удаления элементов из массива). Это осуществляется за счет уменьшения количества операций, связанных с перераспределением памяти.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *