4.6. Вектор
Для того чтобы программа делала полезную работу, необходимо хранить коллекцию данных. Например, нам может понадобиться список телефонных номеров, список игроков футбольной команды, список книг, прочитанных в прошлом году, список курсов, график платежей за автомобиль, список прогнозов погоды на следующую неделю, список цен на фотокамеру в интернет-магазине и т.д. Этот перечень можно продолжать до бесконечности, а потому и в программах эти списки встречаются очень часто. В дальнейшем мы рассмотрим множество способов хранения коллекций данных (контейнерные классы, описанные в главах 20 и 21). Пока начнем с простейшего и, вероятно, наиболее полезного способа хранения данных: типа
vector
(вектор).
Вектор — это последовательность элементов, к которым можно обращаться по индексу. Например, рассмотрим объект типа
vector
с именем
v
.
Иначе говоря, индекс первого элемента равен 0, индекс второго элемента — 1 и т.д. Мы ссылаемся на элемент, указывая имя вектора и индекс элемента в квадратных скобках, так что значение
v[0]
равно
5
, значение
v[1]
равно
7
и т.д. Индексы вектора всегда начинаются с нуля и увеличиваются на единицу. Это вам должно быть знакомым: вектор из стандартной библиотеки С++ — это просто новый вариант старой и хорошо известной идеи. Я нарисовал вектор так, как показано на рисунке, чтобы подчеркнуть, что вектор “знает свой размер”, т.е. всегда хранит его в одной из ячеек.
Такой вектор можно создать, например, так:
vector<int> v(6); // вектор из 6 целых чисел
v[0] = 5;
v[1] = 7;
v[2] = 9;
v[3] = 4;
v[4] = 6;
v[5] = 8;
Как видим, для того чтобы создать вектор, необходимо указать тип его элементов и их начальные значения. Тип элементов вектора указывается после слова
vector
в угловых скобках (
<>
). Здесь использован тип
<int>
, а количество элементов указано после имени в круглых скобках (
(6)
). Рассмотрим еще один пример.
vector<string> philosopher(4); // вектор из 4 строк
philosopher [0] = "Kant";
philosopher [1] = "Plato";
philosopher [2] = "Hume";
philosopher [3] = "Kierkegaard";
Естественно, в векторе можно хранить элементы только одного типа.
philosopher[2] = 99; // ошибка: попытка присвоить целое число строке
v[2] = "Hume"; // ошибка: попытка присвоить строку целому числу
Когда мы объявляем объект типа
vector
с заданным размером, его элементы принимают значения, заданные по умолчанию для указанного типа. Рассмотрим пример.
vector<int> v(6); // вектор из 6 целых чисел инициализируется нулями
vector<string> philosopher(4); // вектор из 4 строк инициализируется
// значениями ""
Если вам не подходят значения, заданные по умолчанию, можете указать другие. Рассмотрим пример.
vector<double> vd(1000,–1.2); // вектор из 1000 действительных
// чисел, инициализированных как –1.2
Пожалуйста, обратите внимание на то, что мы не можем просто сослаться на несуществующий элемент вектора.
vd[20000] = 4.7; // ошибка во время выполнения программы
Ошибки, возникающие во время выполнения программы, и работа с индексами описаны в следующей главе.
4.6.1. Увеличение вектора
Часто мы начинаем работу с пустым вектором и увеличиваем его размер по мере считывания или вычисления данных. Для этого используется функция
push_back()
, добавляющая в вектор новый элемент. Новый элемент становится последним элементом вектора. Рассмотрим пример.
vector<double> v; // начинаем с пустого вектора,
// т.е. объект v не содержит ни одного элемента
v.push_back(2.7); // добавляем в конец вектора v элемент
// со значением 2.7
// теперь вектор v содержит один элемент
// и v[0]==2.7
v.push_back(5.6); // добавляем в конец вектора v элемент
// со значением 5.6
// теперь вектор v содержит два элемента
// и v[1]==5.6
v.push_back(7.9); // добавляем в конец вектора v элемент
// со значением 7.9
// теперь вектор v содержит три элемента
// и v[2]==7.9
Обратите внимание на синтаксис вызова функции
push_back()
. Он называется
вызовом функции-члена; функция
push_back()
является функцией-членом объекта типа
vector
, и поэтому для ее вызова используется особая форма вызова.