Выбрать главу

std::string zzz {"zzz"};

within(aaa, zzz, bcd, def); // --> true

within(aaa, def, bcd, zzz); // --> false

Отправка нескольких элементов в вектор

Кроме того, вы можете написать вспомогательную функцию, которая не обобщает никаких результатов, но обрабатывает несколько действий одного вида. Такими действиями могут быть вставки элементов в контейнер std::vector, поскольку они не возвращают никаких результатов (функция std::vector::insert() сообщает об ошибке, генерируя исключения):

template <typename T, typename ... Ts>

void insert_all(std::vector<T> &vec, Ts ... ts)

{

  (vec.push_back(ts), ...);

}

int main()

{

  std::vector<int> v {1, 2, 3};

  insert_all(v, 4, 5, 6);

}

Обратите внимание: мы используем оператор «запятая» (,), чтобы распаковать пакет параметров в отдельные вызовы vec.push_back(...), не выполняя свертку для самого результата. Эта функция также хорошо работает в отношении пустого пакета параметров, поскольку оператор «запятая» имеет неявный нейтральный элемент, void(), который означает «ничего не делать». 

Глава 2

Контейнеры STL

В этой главе:

□ использование идиомы erase-remove для контейнера std::vector;

□ удаление элементов из неотсортированного контейнера std::vector за время O(1);

□ получение доступа к экземплярам класса std::vector быстрым или безопасным способом;

□ поддержка экземпляров класса std::vector в отсортированном состоянии;

□ вставка элементов в контейнер std::map: эффективно и в соответствии с условиями;

□ исследование новой семантики подсказок для вставки элементов с помощью метода std::map::insert;

□ эффективное изменение ключей элементов std::map;

□ применение контейнера std::unordered_map для пользовательских типов;

□ отбор повторно встречающихся слов из пользовательского ввода и вывод их на экран в алфавитном порядке с помощью контейнера std::set;

□ реализация простого ОПН-калькулятора с использованием контейнера std::stack;

□ подсчет частоты встречаемости слов с применением контейнера std::map;

□ реализация вспомогательного инструмента для поиска очень длинных предложений в текстах с помощью std::multimap;

□ реализация личного списка текущих дел с помощью std::priority_queue.

Введение

В стандартной библиотеке С++ появилось большое количество стандартных контейнеров. Контейнер всегда содержит набор данных или объектов. Достоинство контейнеров в том, что их можно применять практически для всех объектов, поэтому нужно только выбрать правильные контейнеры для конкретного приложения. STL предоставляет стеки, автоматически увеличивающиеся векторы, ассоциативные массивы и т.д. Таким образом, можно сконцентрироваться на нашем приложении и не изобретать велосипед. В целом каждому программисту С++ не повредит знакомство со всеми контейнерами.

Все контейнеры, предоставляемые STL, можно разделить на такие категории, которые подробнее рассматриваются в следующем разделе:

□ непрерывные хранилища;

□ списки;

□ деревья поиска;

□ хеш-таблицы;

□ адаптеры контейнеров.

Рассмотрим более подробно каждый из пунктов.

Непрерывные хранилища

Самый простой способ хранения объектов — поместить их рядом друг с другом в одном большом фрагменте памяти. Произвольный доступ к такому фрагменту выполняется за время O(1).

Это проще всего сделать так: воспользоваться контейнером std::array (он представляет собой обертку для обычных массивов в стиле C). Вам практически всегда следует выбирать их вместо обычных массивов, поскольку это не потребует никаких усилий, но работать станет комфортнее и безопаснее. Как и в случае с обычными массивами, массивы STL имеют фиксированный размер, определяемый при создании.

Контейнер std::vector вступает в дело, когда вам нужно хранилище, похожее на массив, но с изменяемой длиной. Он использует память из кучи для хранения объектов. Если при добавлении элемента в вектор происходит превышение размера вектора, то все элементы автоматически перемещаются в более крупный фрагмент вновь выделенной памяти, старый же фрагмент удаляется. Более того, если новый элемент помещается между двумя старыми, то может даже перемещать существующие элементы в памяти. При удалении элемента из середины вектора класс vector автоматически сдвинет оставшиеся элементы так, чтобы закрыть получившуюся дыру.