- •2 Часть
- •Источники информации
- •1.2 Введение вStl
- •1.2.1 Обзор библиотеки
- •1.2.2 Базовые понятия
- •2 Контейнеры
- •2.1 Простые контейнеры
- •2.1.1 Пара (Pair/Tuple)
- •2.2 Контейнеры с последовательным доступом
- •2.2.1 Вектор (vector)
- •2.2.2 Список (list)
- •2.2.3Forward_list
- •2.2.4 Очередь двухсторонняя (deque)
- •2.3 Контейнеры-адаптеры
- •2.3.1 Очередь односторонняя (queue)
- •2.3.2 Очередь с приоритетами (priority queue)
- •2.3.3 Стек (stack)
- •2.4 Контейнеры с доступом к случайным элементам
- •2.4.1 Упорядоченное множество элементов (set)
- •2.4.2Multiset
- •2.4.3 Словарь (map)
- •2.4.4Multimap
- •3 Итераторы
- •4 Алгоритмы
- •4.1 Не модифицируют коллекцию
- •4.1.1 All_of / any_of / none_of
- •4.1.2For_each
- •4.1.3 Find / find_if / find_if_not / find_end / find_first_of
- •4.1.4Count/count_if
- •4.2.2Move/move_backward
- •4.4.2Partial_sort/partial_sort_copy
- •6 БудущееStl
- •7 Наследование и работа с памятью вStl
3 Итераторы
Итераторы выступают в роли прослойки между различными типами контейнеров и алгоритмами. Алгоритмы работают в основном с итераторами. Передается итератор от какого элемента и итератор конечного элемента.
Итератор указывает на элемент. Он может ходить по коллекции вперед, назад, получать и получать, добавлять, менять элементы (некоторые типы итераторов в операциях более ограничены). У коллекций есть методы вида: дай итератор начала (begin()), дай итератор конца (end()). Итератор начала указывает на первый элемент. Итератор конца указывает за конечный элемент. Чтобы ходить вперед по итератору, нужно делать ++итератор. Чтобы получать значение по итератору, можно написать *итератор. Большинство итераторов сделаны в виде внутренних классов контейнеров и их экземпляры поэтому создаются как-то так: шаблонный_тип<шаблонные_аргументы>::iterator=коллекция.begin(). Поскольку такая форма слишком объемная, то используется
В других языках концепт с итераторами поменялся. Выяснилось, что ходить назад, а также менять элементы мало кому нужно. Также интерфейс итератора поменялся. Теперь он выглядит как-то так:
interface Iterator<TData>
{
TData GetElement();
boolMovNext();
voidReset();
}
4 Алгоритмы
Алгоритмы условно разделили на несколько групп. Примеры и идеи для примеров частично взяты с http://www.cplusplus.com/reference. Все алгоритмы связаны с работой с коллекциями. Аналог алгоритмов в таких языка какC# -Linq.
4.1 Не модифицируют коллекцию
Поверхностное знакомство с анонимными функторами. Анонимный функтор – то же самое, что и указатель на подпрограмму.
#include "stdafx.h"
#include <iostream>
using namespace std;
void Print(int x)
{
cout << x << " ";
}
void PrintArray(void(*printElementPointer)(int), const int* array, int size)
{
for (int i = 0; i < size; i++)
{
printElementPointer(array[i]);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int data[] = { 13, 10, 666 };
PrintArray(Print, data, 3);
getchar();
}
Указатель на подпрограмму передается в какую-то подпрограмму, которая с помощью него нечто вытворяет. Например, подпрограмме печати нужно каждый раз как-то по-особому печатать. Теперь это представим в виде лямбда-выражения.
#include "stdafx.h"
#include <iostream>
using namespace std;
void PrintArray(void(*printElementPointer)(int), const int* array, int size)
{
for (int i = 0; i < size; i++)
{
printElementPointer(array[i]);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int data[] = { 13, 10, 666 };
PrintArray(
[](int x) {cout << x << " "; },
data,
3);
getchar();
}
Как видите, вместо адреса функции можно напрямую объявить саму функцию. Лямбда-выражение начинают с []. Затем идет тело функции. Неявно компилятор создаст подпрограмму из лямбда-выражения и подставит адрес функции.
4.1.1 All_of / any_of / none_of
Все элементы (как минимум один элемент / ни один из элементов) соответствуют условию.
Пример:
#include "stdafx.h"
#include <array>
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
std::array<int, 2> data = { 13, 55 };
if (std::all_of(
data.begin(),
data.end(),
[](int i){return i % 2; }))
{
std::cout << "All the elements are odd numbers.\n";
}
return 0;
}