Неизвестные типы и пространство неизвестных имен. Динамическое определение типов. Операторы переключения типов. Создание пространства новых имен. Буферизированный вход и выход. Содержание
Скачать 0.92 Mb.
|
PRESENTATION
Безусловно, наиболее часто используемым функционалом библиотеки STL являются контейнерные классы (или как их еще называют — «контейнеры»). Библиотека STL содержит много разных контейнерных классов, которые можно использовать в разных ситуациях. Если говорить в общем, то контейнеры STL делятся на три основные категории: последовательные; ассоциативные; адаптеры. Сейчас сделаем их краткий обзор. Оглавление:
Последовательные контейнеры Последовательные контейнеры (или «контейнеры последовательности») — это контейнерные классы, элементы которых находятся в последовательности. Их определяющей характеристикой является то, что вы можете добавить свой элемент в любое место контейнера. Наиболее распространенным примером последовательного контейнера является массив: при добавлении 4 элементов в массив, эти элементы будут находиться (в массиве) в точно таком же порядке, в котором вы их добавили. Контейнеры STL Начиная с C++11, STL содержит 6 контейнеров последовательности: std::vector; std::deque; std::array; std::list; std::forward_list; std::basic_string. Класс vector (или просто «вектор») — это динамический массив, способный увеличиваться по мере необходимости для содержания всех своих элементов. Класс vector обеспечивает произвольный доступ к своим элементам через оператор индексации [], а также поддерживает добавление и удаление элементов. В следующей программе мы добавляем 5 целых чисел в вектор и с помощью перегруженного оператора индексации [] получаем к ним доступ для их последующего вывода
Класс deque (или просто «дек») — это двусторонняя очередь, реализованная в виде динамического массива, который может расти с обоих концов. Например: #include #include int main() { std::deque for (int count=0; count < 4; ++count) { deq.push_back(count); // вставляем числа в конец массива deq.push_front(10 - count); // вставляем числа в начало массива } for (int index=0; index < deq.size(); ++index) std::cout << deq[index] << ' '; std::cout << '\n'; } List (или просто «список») — это двусвязный список, каждый элемент которого содержит 2 указателя: один указывает на следующий элемент списка, а другой — на предыдущий элемент списка. List предоставляет доступ только к началу и к концу списка — произвольный доступ запрещен. Если вы хотите найти значение где-то в середине, то вы должны начать с одного конца и перебирать каждый элемент списка до тех пор, пока не найдете то, что ищете. Преимуществом двусвязного списка является то, что добавление элементов происходит очень быстро, если вы, конечно, знаете, куда хотите добавлять. Обычно для перебора элементов двусвязного списка используются итераторы. Хотя о классе string (и wstring) обычно не говорят, как о последовательном контейнере, но он, по сути, таковым является, поскольку его можно рассматривать как вектор с элементами типа char (или wchar). Ассоциативные контейнеры Ассоциативные контейнеры — это контейнерные классы, которые автоматически сортируют все свои элементы (в том числе и те, которые добавляете вы). По умолчанию ассоциативные контейнеры выполняют сортировку элементов, используя оператор сравнения <. set — это контейнер, в котором хранятся только уникальные элементы, и повторения запрещены. Элементы сортируются в соответствии с их значениями. multiset — это set, но в котором допускаются повторяющиеся элементы. map (или «ассоциативный массив») — это set, в котором каждый элемент является парой «ключ-значение». «Ключ» используется для сортировки и индексации данных и должен быть уникальным, а «значение» — это фактические данные. multimap (или «словарь») — это map, который допускает дублирование ключей. Все ключи отсортированы в порядке возрастания, и вы можете посмотреть значение по ключу. Адаптеры Адаптеры — это специальные предопределенные контейнерные классы, которые адаптированы для выполнения конкретных заданий. Самое интересное заключается в том, что вы сами можете выбрать, какой последовательный контейнер должен использовать адаптер. stack (стек) — это контейнерный класс, элементы которого работают по принципу LIFO (англ. «Last In, First Out» = «последним пришел, первым ушел»), т.е. элементы добавляются (вносятся) в конец контейнера и удаляются (выталкиваются) оттуда же (из конца контейнера). Обычно в стеках используется deque в качестве последовательного контейнера по умолчанию (что немного странно, поскольку vector был бы более подходящим вариантом), но вы также можете использовать vector или list. queue (очередь) — это контейнерный класс, элементы которого работают по принципу FIFO (англ. «First In, First Out» = «первым пришел, первым ушел»), т.е. элементы добавляются (вносятся) в конец контейнера, но удаляются (выталкиваются) из начала контейнера. По умолчанию в очереди используется deque в качестве последовательного контейнера, но также может использоваться и list. Контейнеры и итераторы Контейнер container — класс, объекты которого способны хранить набор однотипных значений (обобщение понятия “массив”). Контейнер предоставляет средства доступа к своему содержимому. В Стандартной библиотеке C++ эти средства доступа строятся на обобщении понятия “указатель на элемент массива”, которое носит название итератор iterator. Пара итераторов задаёт диапазон range — определение последовательности значений, которую можно перечислить, передвигая итератор вперёд, начиная с первого элемента, на который указывает первый итератор в паре, и до тех пор, пока не будет встречен второй итератор в паре, обозначающий конец последовательности и указывающий на фиктивный элемент, как бы стоящий в последовательности сразу за последним элементом. Последовательность может представлять собой контейнер, часть контейнера, массив, файл или генерироваться “на ходу”. Пример диапазона с массивом: char data[] = "Hello, world!"; // Диапазон с 7-го элемента по 12-й содержит слово "world". auto begin = data + 7; // Начало диапазона -- первый итератор в паре. auto end = data + 12; // Конец диапазона -- второй итератор в паре. assert(end - begin == 5); // Расстояние между итераторами == количеству элементов в диапазоне. // Перечислим подряд все элементы диапазона. while (begin != end) cout.put(*begin++); // > world |