Освой самостоятельно С++ за 21 день.
Шрифт:
Функция шаблона ShowVector объявлена в строках 74—75 и определена в строках 115-128. Она используется для вызова функций-членов вектора, отображающих его свойства: max_size, size, capacity и empty. Насколько можно судить по результатам работы этой программы, максимальное число объектов класса Student, которое может принять этот вектор, в Visual C++ составляет 214 748 364. Для других типов элементов это число может быть другим. Например, вектор целых чисел может вместить до 1 073 741 823 элементов. Если же вы используете другие компиляторы, то максимальное число элементов у вас может отличаться от приведенных здесь значений.
В строках 124
В строках 81—84 создаются четыре объекта класса Student. В строке 86 с помощью стандартного конструктора векторного класса определяется пустой вектор с именем EmptyClass. Когда вектор создается таким способом, то компилятор для него совсем не выделяет места в памяти. Как видно по результатам работы функции ShowVector(EmptyClass), как размер, так и вместимость этого вектора равны нулю.
Строка 90 содержит определение вектора для включения трех объектов класса Student. Размер и вместимость этого вектора, как и ожидалось, равны трем. В строках 94—96 с помощью оператора индексирования ([]) элементы вектора GrowingClass заполняются объектами класса Student.
В строке 100 к вектору добавляется четвертый студент (Peter). Это увеличивает размер вектора до четырех элементов. Интересно, что его вместимость теперь установлена равной шести. Это означает, что компилятор автоматически выделил достаточно пространства, которого хватит даже для шести объектов класса Student. Поскольку векторам должен быть выделен непрерывный блок памяти, для их расширения требуется выполнить целый ряд операций. Сначала выделяется новый блок памяти, достаточно большой для всех четырех объектов класса Student. Затем в только что выделенную память копируются эти три элемента, а четвертый добавляется после третьего элемента. И наконец, исходный блок памяти возвращается в область динамического обмена. При большом количестве элементов в векторе процесс перераспределения и освобождения памяти может оказаться весьма длительным. Поэтому в целях сокращения вероятности выполнения таких дорогих (по времени) операций компилятор использует стратегию оптимизации. В данном примере, если сразу добавить к вектору еще один или два объекта, отпадает необходимость в дополнительных операциях, связанных с освобождением и перераспределением памяти.
В строках 104 и 105 вновь используется оператор индексирования ([]), чтобы изменить переменные-члены первого объекта в векторе GrowingClass.
Рекомендуется:Определяйте стандартный конструктор для класса, если его объекты будут содержаться в векторе. Определяйте конструктор-копировщик для такого класса. Определяйте для такого класса перегруженный оператор присваивания.
Класс-контейнер вектора имеет и другие функции-члены. Функция front возвращает ссылку на первый элемент в списке, а функция back — на последний. Функция at работает подобно оператору индексирования ([]). Она более безопасна, поскольку проверяет, попадает ли переданный ей индекс в диапазон доступных элементов. Если адрес оказывается вне диапазона, эта функция генерирует исключение out_of_range. (Исключительные ситуации рассматриваются на следующем занятии.)
Функция insert вставляет один или несколько узлов (элементов) в текущую позицию вектора. Функция Pop_back удаляет из вектора последний элемент. Наконец, функция remove удаляет из вектора один или несколько элементов.
Список
Список — это контейнер, разработанный для обеспечения оптимального выполнения частых вставок и удалений элементов.
Класс-контейнер библиотеки STL list определен в файле заголовка <list> в пространстве имен std. Класс list выполнен как двунаправленный связанный список, в котором каждый узел содержит указатели как на предыдущий, так и на последующий узел списка.
Класс list имеет все функции-члены, предоставляемые векторным классом. Как вы помните, список можно пройти, следуя по связям между узлами, реализованным с помощью указателей. Стандартный класс-контейнер list с той же целью использует алгоритм, называемый итератором.
Итератор — это обобщение указателя. Чтобы отыскать узел, на который указывает итератор, его нужно разыменовывать. Использование итераторов для доступа к узлам списка демонстрируется в листинге 19.9.
Листинг 19.9. Навигация по списку с ппмощью итератора
1: #include <iostream>
2: #include <list>
3: using namespace std;
4:
5: typedef list<int> IntegerList;
6:
7: int main
8: {
9: IntegerList intList;
10:
11: for (int i = 1; i <= 10; ++i)
12: intList.push_back(i * 2);
13:
14: for (IntegerList::const_iterator ci = intList.begin;
15: ci!= intList.end; ++ci)
16: cout << *ci << " ";
17:
18: return 0;
19: }
Результат:
2 4 6 8 10 12 14 16 18 20
Анализ: В строке 9 объект intList определен как список целых чисел. В строках 11 и 12 с помощью функции push_back в список добавляются первые 10 положительных четных чисел.
В строках 14-16 мы обращаемся к каждому узлу в списке, используя константный итератор. Константность указывает, что мы не собираемся изменять узлы с помощью этого итератора. Если бы мы хотели изменить узел, на который указывает итератор, пришлось бы использовать переменный итератор:
intList::iterator
Функция-член begin возвращает итератор на первый узел списка. Оператор инкремента (++) можно использовать для перехода к итератору следующего узла. Функция-член end, что может показаться странным, возвращает итератор на узел, расположенный за последним узлом списка. Часто метод end используют для определения допустимых границ списка.
Разыменование итератора (для возвращения связанного с ним узла) происходит аналогично разыменованию указателя, как показано в строке 16.
Хотя понятие итератора было введено только при рассмотрении класса list, итераторы можно использовать и с векторными классами. В дополнение к функциям-членам, с которыми вы познакомились в векторном классе, базовый класс списка тоже представляет функции push_front и pop_front, которые работают точно так же, как и функции push_back и pop_back. Но вместо добавления и удаления элементов в конце списка, они добавляют и удаляют элементы в его начале.
Контейнер двухсторонней очереди