Статьи

С ++ Кратко: C ++ Стандартная библиотека

В стандартной библиотеке C ++ гораздо больше вещей, чем мы успеваем осветить. Мы ограничимся рассмотрением некоторых наиболее часто используемых функций, которые мы еще не исследовали.

Итераторы служат той же цели, что и IEnumerable и связанные интерфейсы в .NET, например, предоставляют общий способ навигации по коллекциям. Например, для std::vector вы можете просмотреть его коллекцию элементов с помощью следующего кода:

01
02
03
04
05
06
07
08
09
10
11
12
vector<int> vec;
   vec.push_back(1);
   vec.push_back(4);
   vec.push_back(7);
   vec.push_back(12);
   vec.push_back(8);
    
    
   for (auto i = begin(vec); i != end(vec); i++)
   {
       wcout << *i << endl;
   }

Функция std::begin предоставляет итератор, указывающий на первый элемент коллекции. std::end предоставляет итератор, который сообщает, что мы достигли конца коллекции; последний элемент коллекции, при условии, что в коллекции есть какие-либо элементы, — это один элемент перед элементом, который нам передается с помощью std::end . Вот почему мы проверяем! = В цикле for. Если в коллекции нет элементов, то std::begin и std::end вернут одно и то же значение.

В дополнение к итераторам из этих двух шаблонных функций, многие коллекции предоставляют константные итераторы через функции-члены с именами cbegin и cend, обратные итераторы (которые перебирают коллекцию в обратном направлении) через rbegin и rend , и const обратные итераторы через crbegin и crend . В предыдущем примере вы можете заменить begin(vec) на vec.rbegin() и end(vec) на vec.rend() чтобы пройти через вектор в обратном порядке.


В C ++ 11 добавлен дополнительный тип цикла for, называемый циклом for на основе диапазона, который обеспечивает функциональность, аналогичную циклу foreach в C #. Циклический цикл for использует итераторы и избавляет вас от необходимости отмены ссылок на указатели и возможности неправильной проверки конца. Основанный на диапазоне цикл for, эквивалентный циклу for в предыдущем примере, выглядит следующим образом:

1
2
3
4
for (auto item : vec)
   {
       wcout << item << endl;
   }

Коллекция, которую вы, скорее всего, будете использовать, это std::vector . Это быстрая, универсальная коллекция, похожая на List <T> в .NET. Он находится в заголовочном файле <vector>.

Чтобы добавить элемент в конец вектора, используйте функцию-член push_back . Чтобы удалить элемент из конца вектора, используйте pop_back . Вы можете получить доступ к элементам по их индексу, используя [] так же, как и массив. Чтобы добавить элемент или диапазон элементов с определенным индексом, начинающимся с нуля, используйте функцию-член insert. Чтобы удалить элемент или диапазон элементов с определенным индексом, начинающимся с нуля, используйте функцию-член стирания.

Отличная особенность, добавленная в C ++ 11, — это функциональность конструирования на месте, предоставляемая функциями-членами emplace и emplace_back. Вместо того, чтобы создавать объект и затем использовать insert или push_back для добавления его в вектор, вы можете вызвать emplace_back и просто передать ему те же аргументы, которые вы передадите конструктору для типа, который содержит вектор. Затем вектор создаст и добавит новый экземпляр объекта без дополнительных вычислений, сопровождающих копию или перемещение, и без использования дополнительной локальной памяти.

Функция emplace работает так же, за исключением того, что вы начинаете с передачи ей итератора, который указывает местоположение. Вы можете использовать cbegin() или cend() для добавления элементов в начало или конец вектора. Если у вас есть определенный нулевой индекс, в который вы хотите поместить элемент, вы можете использовать vec.cbegin() + idx . Вы также можете вычесть из cend() если хотите поместить элемент на некоторое количество пробелов с конца.

Vector предлагает больше функциональности, поэтому вам обязательно стоит изучить его дальше. Функция at member даст вам элемент по индексу, например. Есть способы сообщить вектору, что нужно изменить размер его внутренней емкости, чтобы у вас было больше свободного места — если бы вы знали, что вам понадобится ровно 125 элементов, например — или вы минимизировали использование памяти — если вы добавили все элементы, которые ему когда-либо понадобятся, и ограничения памяти жесткие.

В дополнение к std::vector , несколько похожих контейнеров имеют разные варианты использования. Сам std::vector — лучший выбор, когда вам нужен чрезвычайно быстрый произвольный доступ — когда вы будете в основном добавлять элементы и удалять элементы из самого конца коллекции. Если вам также необходимо часто добавлять элементы в начало коллекции, вам следует рассмотреть возможность использования std::deque .

Используйте std::queue для контейнера «первым вошел, первым вышел». Используйте std :: stack для контейнера «последний пришел — первый вышел».

Класс std::map предоставляет отсортированный словарь. std::unordered_map предоставляет хеш-таблицу.

Класс std::set представляет собой отсортированную коллекцию ключей, в которой сохраненный элемент является собственным ключом, поэтому каждый элемент должен быть уникальным. std::unordered_set является несортированным эквивалентом std::set .

Класс std::list предоставляет двусвязный список. std::forward_list предоставляет односвязный список.

Заголовок <алгоритма> содержит много очень полезных функций: такие как поиск, сортировка, копирование и все связанные с ними методы. Лучший способ выучить их — поэкспериментировать с ними.

Некоторые функции из библиотеки времени выполнения C могут быть полезны. Как правило, лучший способ получить доступ к библиотеке — включить соответствующий заголовочный файл <c _____>, например <cstdlib>.

Стандартная библиотека C ++ может предложить гораздо больше, поэтому я настоятельно рекомендую изучить ее и ознакомиться с ней. В заключительной статье этой серии мы рассмотрим Visual Studio и то, как он лучше всего используется для разработки на C ++.

Этот урок представляет собой главу из C ++ Succinctly , бесплатной книги от команды Syncfusion .