Контейнер vector в C++

Материал из Энциклопедия о программировании
Перейти к: навигация, поиск

vector (он же массив vector, полностью (вместе с пространств. имён, где он определён) std::vector, транслит. вектор) — шаблонный класс контейнера последовательности, представляющий массив, размер которого может динамически изменяться. Официальная замена в C++ стандартному динамическому массиву C.

Особенности

Память для вектора выделяется динамически, что можно сделать и вручную с помощью оператора new.

Рекомендации

Разработчики языка C++ рекомендуют в использовать именно vector вместо ручного выделения памяти для обычного массива. Это позволяет избежать утечек памяти и облегчает работу программисту.

В C и C++ имеются некоторые серьёзные неудобства при работе с обычными массивами, поэтому при работе с C++ чаще всего используют именно массивы типа vector как базовые.

Заголовочные файлы

Для работы со стандартными для C++ векторами надо обязательно подключить заголовочный файл «vector» (без Си суффикса/расширения «.h», т.к. это заголовочный файл сугубо C++, т.е. пишется просто <vector>):

#include <vector>

Примеры

Декларация и инициализация

Этот раздел также можно назвать, или альтернативные заголовки раздела:
  • Создание/определение вектора и задание его значений
Пустые именованные вектора

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

std::vector<float> vec;

или с явным вызовом конструктора без параметров:

std::vector<int> vec();
Пустые и непустые безымянные вектора

Пустой безымянный вектор:

std::vector<int>();

Непустой/заполненный безымянный вектор:

std::vector<int>{5, 8};
Создание и задание вектора

Вектор типа int из заданных элементов:

std::vector<int> vec = {5, 2, 4, 17, 10, 8, 3};

Инициализация вектора подобно массивам:

std::vector<int> vect{ 10, 20, 30 };
Указание размера и авто-заполнение
Этот раздел отвечает на след. вопр.:
  • Как указать размер вектора при его создании?
Этот раздел может соответствовать след. поисковым запросам:
  • с++ vector указать размер при создании

Вектор из 5 пустых элементов типа int, т.е. вектор типа int размером в 5 элем. со знач. 0, что явл. знач. по-умолч. для типа int:
В файле основного текста программы:

std::vector<int> num(5);

В заголовочн. файле:

std::vector<int> num{5};

Вектор, состоящий из 8 элементов типа int, по-умолч. все элементы заполняются числом 5:
В файле основного текста программы:

std::vector<int> vec(8, 5);

В заголовочн. файле:

std::vector<int> vec{8, 5};
Автоматическое создание и заполнение из других векторов и массивов

Инициализация вектора из массива. Результирующий вектор будет аналогом массива, т.е. будет такой же длинны/размера и содержать все элементы массива в том же порядке:

int arr[] = {10, 20, 30};
int n = sizeof(arr) / sizeof(arr[0]);
std::vector<int> vect(arr, arr + n);

Инициализация вектора из другого вектора:

std::vector<int> vect1{ 10, 20, 30 }; 
std::vector<int> vect2(vect1.begin(), vect1.end());

Инициализация всех элементов определенным значением с помощью функции заливки std::fill (необходимо подключение хедера «algorithm»):

#include <algorithm>
// ...
std::vector<int> vect1(10); 
int value = 5; 
std::fill(vect1.begin(), vect1.end(), value);

Копирование вектора. Создание одного вектора на основе другого. Создание вектора и заполнение его другим, т.е. элементами др. вектора:

std::vector<int> third = {2, 7, 12, 18, 25};
std::vector<int> fourth(third);

Динамически создаваемый находящийся в управляемой куче вектор

Создание указателя на динамически создаваемый находящийся в управляемой куче вектор:

std::vector<int>* vec;

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

std::vector<int>* vec = new std::vector<int>();

Декларация и дефинация

Дефинация

std::vector<int> arr; // декларация
arr = {5, 8, 14}; // дефинация

Задать 3 элемента, каждый имеет значение 5:

std::vector<int> vec;
vec.assign(3, 5);

Добавление

std::vector<int> arr; // декларация
arr.push_back(3); // добавление нового элемента в конец

Управление элементами вектора

Добавление/вставка нового элемента в конец вектора с помощью метода push_back:

std::vector<int> vect;
vect.push_back(10);

Вставка нового элемента в начало (остальные элементы сдвигаются):

std::vector<int> arr;
arr.insert(arr.begin(), 8);

Удаление элемента из начала (остальные элементы сдвигаются):

std::vector<int> arr;
arr.erase(arr.begin());

Перебор элементов вектора

Стандартный перебор элементов вектора с помощью цикла for:

std::vector<int> vect = {5, 2, 4, 17, 10, 8, 3};
for (unsigned int i = 0; i < vect.size(); i++) {
	std::cout << vect[i] << std::endl; 
}

Перебор элементов вектора с помощью цикла foreach:

std::vector<int> vect = {5, 2, 4, 17, 10, 8, 3};
for (int x : vect) {
	std::cout << x << std::endl;
}

Перебор элементов вектора с помощью итератора:

std::vector<int> vect = {5, 2, 4, 17, 10, 8, 3};
std::vector<int>::iterator it;
for (it = vect.begin(); it != vect.end(); it++) {
	std::cout << *it << std::endl;
}

Стандартный перебор элементов динамически создаваемого находящегося в управляемой куче вектора через указатель на него с помощью цикла for:

std::vector<int>* vec = new std::vector<int>();
vec->push_back(2);
vec->push_back(5);
for (unsigned int i = 0; i < vec->size(); i++) {
	std::cout << vec->at(i) << std::endl;
}

Разное поведение uniform-инициализации

Этот раздел также можно назвать, или альтернативные заголовки раздела:
  • Различное поведение uniform-инициализации вектора в зависимости от типа файла
  • Различное поведение uniform-инициализации вектора в зависимости от контекста

Поведение uniform-инициализации контейнеров-векторов различается в зависимости от контекста, т.е. от того, где это написано - в описании сложного/составного типа данных (класса или структуры), что обычно делается в заголовочн. файле (.h), или во всём остальном, что обычно пишется в файле основного текста программы (.cpp).

СтейтментЧто будет, если это написано в(о)
описании сост. типа дан. (класса/структуры)всём остальном
std::vector<int> num{7}; Создаст 7 пустых ячеек, т.е. со знач. по-умолчанию для типа (для int это 0). Создаст 1 ячейку со знач. 7, т.е. просто добавит 7 в массив.
std::vector<int> num{7, 5}; Создаст 7 ячеек со значением 5. Создаст 2 ячейки со знач. 7 и 5, т.е. просто добавит 7 и 5 в массив.
std::vector<int> num{7, 5, 9}; Выдаст ошибку о том, что к классе-шаблоне vector нет функции, принимающей столько аргументов. Создаст 3 ячейки со знач. 7, 5 и 9, т.е. просто добавит 7, 5 и 9 в массив.

Такое поведение имеет место быть, по крайней мере, в стандарте C++11 в IDE Visual Studio 2013.

Операторы

Операторы класса vector:

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

Методы

Методы класса vector:

  • vector – конструктор. Принимает от 0 до 3 параметров.
  • push_back – доб. нов. эл-та в конец
  • size – кол-во эл-ов
  • pop_back – удал. последн. эл-нт
  • clear – удал. все эл-ты
  • empty – проверить на пустоту
  • insert – встав. нов. эл-нт
  • erase – удал. 1 эл-нт, либо диапазон эл-ов.
  • resize – изменяет размер контейнера, чтобы он содержал указанное кол-во эл-ов, когда уже задан какой-либо размер.
  • assign – присваивает нов. содерж., заменяя его текущ. содержимое и соответств. обр. изменяя его размер.

Отличия от массивов

Несмотря на то, что вектора полностью покрывают функционал массивов, всё же у массивов есть некоторые существенные отличия, что могут быть расценены как их достоинства перед векторами.

Указание размеров в заголовочных файлах

В заголовочных файлах и массивы и вектора нельзя инициализировать (задавать знач. при декларации) и дефинировать (задавать знач. после декларации) какими-либо значениями. Но, массивам можно указать/задавать размер при их декларации в заголовочных файлах, а векторам - нет. Т.е., в отличии от обычных массивов, при декларации векторов в заголовочных файлах никак нельзя указать/задать их размер. Однако uniform-инициализация, что ведёт себя по-разному в зависимости от типа файла, позволяет задать размер вектора при декларации в заголовочн. файлах.

Примеры

Для массива можно задать размер при декларации в заголовоч. файле:

int num[8];

или динамически:

int* num = new int[7];

Для вектора так сделать нельзя:

std::vector<int> num(5);

В этом случ., напр., в IDE Visual Studio IntelliSense будет подчёркивать красным число, что указывает размер вектора, и говорить, что тут требуется спецификатор типа.

С помощью uniform-инициализации можно задавать размер векторов при декларации их в заголовочн. файлах:

std::vector<int> num{5};

См. также