Слайд 1STL
STL (Standard Template Library, стандартная библиотека шаблонов) - набор согласованных
обобщённых алгоритмов, контейнеров, средств доступа к их содержимому и различных
вспомогательных функций. Является одной из самых важных составляющих языка C++. Стандартная библиотека шаблонов до включения в стандарт C++ была сторонней разработкой, в начале — фирмы HP, а затем SGI (Silicon Graphics, Inc.).
Стандарт языка не называет её «STL», так как эта библиотека стала неотъемлемой частью языка, однако многие люди до сих пор используют это название, чтобы отличать её от остальной части стандартной библиотеки (потоки ввода/вывода (iostream), подраздел Си и др.).
Библиотека содержит большое количество широко распространённых алгоритмов и структур данных. Например, в ней определены шаблонные классы векторов, списков, очередей и стеков, а так же многочисленные функции для работы с ними.
Поскольку STL состоит из шаблонных классов, её алгоритмы и структуры данных можно применять практически к любым типам данных.
Слайд 2Основу STL составляют пять основных компонентов:
1.Контейнер (container) - хранение набора
объектов в памяти.
2.Итератор (iterator) - обеспечение средств доступа к содержи-мому
контейнера.
3.Алгоритм (algorithm) - определение вычислительной процедуры.
4.Адаптер (adaptor) - адаптация компонентов для обеспечения различного интерфейса.
5.Функциональный объект (functor) - сокрытие функции в объекте для использования другими компонентами.
В дополнение к ним STL содержит один из наиболее важных классов — string. Этот класс определяет тип данных, позволяющих работать с символьными строками как обычно — с помощью операторов, а не функций.
Взаимодействие этих элементов обеспечивает стандартные решения очень широкого круга задач программирования.
Слайд 3Контейнеры — это объекты, хранящие внутри себя другие объекты.
Контейнеры библиотеки
STL можно разделить на четыре категории: последовательные, ассоциативные, контейнеры-адаптеры и
псевдоконтейнеры.
Слайд 5Каждый контейнерный класс определяет набор функций, которые можно к нему
применять. Например, класс list содержит функции для вставки, удаления и
слияния элементов, а класс stack предусматривает функции для выталкивания и заталкивания элементов.
Алгоритмы
Алгоритмы применяются к контейнерам. Они позволяют манипулировать их содержимым: инициализировать, сортировать, искать и преобразовывать содержимое контейнера. Многие алгоритмы применяются к целому диапазону элементов, находящихся в контейнере.
Адаптеры
Адаптер - адаптация компонентов для обеспечения различного интерфейса. Проще говоря, адаптер превращает одну сущность в другую. Например, контейнер queue, создающий стандартную очередь, является адаптером по отношению к контейнеру deque.
Слайд 6Векторы
Наиболее универсальным контейнерным классом является vector, представляющий собой динамический массив,
размеры которого могут меняться по мере необходимости. Несмотря на то,
что вектор является динамическим массивом, для доступа к его элементам используется обычный способ индексации.
Шаблонная спецификация класса vector:
template > class vector
Type определяет тип данных, хранящихся в контейнере, а класс Allocator определяет механизм распределения памяти. По-умолчанию используется стандартный распределитель.
Класс vector содержит следующие конструкторы:
explicit vector(const Allocator &a = Allocator());
explicit vector(size_type num, const T &val = T(), const Allocator &a = Allocator());
vector(const vectortemplate vector(InIter start, InIter end, const Allocator &a = Allocator());
примечание:
explicit запрещает неявное преобразование и указывает на требования явной формы конструктора копий.
Слайд 7Первый конструктор создаёт пустой вектор. Второй — вектор, состоящий из
num элементов., имеющих значение val, которое можно задавать по умолчанию.
Третий конструктор создаёт вектор, содержащий элементы вектора ob. Четвёртый — вектор, состоящий из элементов, лежащих в диапазоне, определённом на интервале start и end.
Пример объявления векторов:
vector iv; //создаётся пустой вектор типа int
vector cv(5); //создаётся вектор типа char, состоящий из //пяти элементов
vector cv2(5, 'x'); //инициализируется вектор типа char, //состоящий из пяти элементов со значениями х
vector iv2(iv); //создаётся вектор типа int, который //инициализируется другим целочисленным //вектором
В классе vector определены следующие операторы сравнения:
==, <, <=, !=, >, >=
Для доступа к элементам вектора определён оператор [ ], работающий, как и в простом массиве.
Слайд 8В классе vector определено большое количество функций-членов и типов. Полный
список можно получить из справки по используемой средой программирования стандартной
библиотеке. Однако есть функции, общие для всех версий STL.
Слайд 9Рассмотрим пример, иллюстрирующий основные операции над векторами.
#include
#include
#include
#include
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
vector v(10); //создаём вектор
из 10 элементов
int i;
//выводим на экран размер вектора
cout << "Size of v = " << v.size() << '\n';
//присваиваем элементам вектора значения
for(i=0; i<10; i++)
v[i] = i + 'a';
Слайд 10
//выводим на экран содержимое вектора
cout
в конец вектора новые элементы,
//размер вектора увеличивается автоматически
for(i=0; i<10; i++)
v.push_back(i+10+'a');
//выводим на экран размер вектора
сout << "New size = " << v.size() << '\n';
//выводим на экран содержимое вектора
cout << "Current contents:\n";
for(i=0; i
cout << v[i] << ' ';
cout << "\n\n";
//изменяем содержимое вектора
for(i=0; i v[i]=toupper(v[i]);
cout << "Modified contents:\n";
for(i=0; i cout << v[i] << ' ';
_getch();
return 0;
}
Результат выполнения программы:
Size of v = 10
Current contents:
a b c d e f g h i j
Extended vector
New size = 20
Current contents:
a b c d e f g h i j k l m n o p q r s t
Modified contents:
A B C D E F G H I J K L M N O P Q R S T
Слайд 11Вставка и удаление элементов вектора
Для вставки элемента в произвольное место
вектора используется функция insert(). Для удаления любого элемента — erase().
#include
#include
#include
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
vector v(10);
vector v2;
char str[]="";
int i;
for(i=0; i v[i] = i + 'a';
for(i=0; str[i]; i++)
v2.push_back(str[i]);
cout << "Starting contents of v:\n";
for (i=0; i cout << v[i] << ' ';
cout << "\n\n";
Слайд 12vector ::iterator p = v.begin();
p+=2;
v.insert(p, 10, 'X');
cout
v = "
insert:\n";
for (i=0; i
cout << v[i] << ' ';
cout << "\n\n";
p=v.begin();
p+=2;
v.erase(p, p+10);
cout << "Size of v = " << v.size() << '\n';
cout << "Contents after erase:\n";
for (i=0; i cout << v[i] << ' ';
cout << "\n\n";
p=v.begin()+2;
v.insert(p, v2.begin(), v2.end());
cout << "Size of v = " << v.size() << '\n';
cout << "Contents after insert:\n";
for (i=0; i cout << v[i] << ' ';
_getch();
return 0;
}
Результат выполнения программы
Starting contents of v:
a b c d e f g h i j
Size of v = 20
Contents after insert:
a b X X X X X X X X X X c d e f g h i j
Size of v = 10
Contents after erase:
a b c d e f g h i j
Size of v = 18
Contents after insert:
a b < V e c t o r > c d e f g h i j
Слайд 13Вектор, содержащий объекты класса
Так как вектор является шаблонным классом, из
этого следует, что его элементами могут быть не только экземпляры
стандартных типов (int, double, и т.п.), но и пользовательские классы. При использовании пользовательских объектов в качестве элементов вектора необходимо помнить, что вектор содержит встроенные операторы сравнения (==, <, <=, !=, >, >=) и присваивания. Поэтому важно не забывать переопределять данные операторы в классе, который будет использоваться в качестве элемента вектора.
Слайд 14Списки
Класс list создаёт двунаправленный линейный список. В отличие от вектора,
предоставляющего произвольный доступ к своим элементам, доступ к элементам списка
может быть только последовательным. Поскольку список является двунаправленным, можно перемещаться от начала к концу списка и наоборот.
Шаблонная спецификация класса list имеет следующий вид
template > class list;
Шаблонный параметр Type задаёт тип данных, хранящихся в списке. Распределитель памяти задаётся классом Allocator, причём по-умолчанию используется стандартный распределитель памяти.
Класс list имеет следующий конструкторы:
explicit list(const Allocator &a = Allocator());
explicit list(size_type num, const Type &val = Type(), const Allocator &a = Allocator());
list(const listtemplate list(InIter start, InIter end, const Allocator &a = Allocator());
Первый конструктор создаёт пустой список. Второй — список, состоящий из num элементов., имеющих значение val, которое можно задавать по-умолчанию.
Слайд 15Третий конструктор создаёт список, содержащий элементы объекта ob. Четвёртый —
формирует список, состоящий из элементов, лежащих в диапазоне, заданном итераторами
start и end.
Как видно из конструкторов — они имеют такой же вид, как и конструкторы векторов. Такая унификация — одна из особенностей STL, благодаря которой, программист может не задумываться об особенностях конструктора определённого контейнера.
Как и в векторе, в list определены следующие операторы сравнения:
==, <, <=, !=, >, >=
В классе list определены функции-члены для работы с элементами класса. Так как данный класс содержит в себе все функции, что и vector (кроме оператора [ ] - его список не поддерживает), внизу приведена таблица функций-членов, специфичных только для списка (т.е. для работы со списком необходимо знать принципы работы с вектором).
Слайд 16Для достижения гибкости и независимости от компиляторов любой объект, помещаемый
в список, должен иметь конструктор по умолчанию. Кроме того, в
нём должны быть определены операторы сравнения, чтобы исключить конфликт с работой этих же операторов самого контейнера.
Слайд 17#include
#include
#include
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
list
lst; // Создаём пустой список
int i;
for(i=0; i
"Size of list = " << lst.size() << '\n';
cout << "Contents: ";
list
::iterator p = lst.begin();
while (p!=lst.end()){
cout << *p << ' ';
p++;
}
cout << "\n\n";
//Изменяем содержимое списка
p=lst.begin();
while (p!=lst.end()){
*p=*p + 100;
p++;
}
cout << "Modified contents: ";
p=lst.begin();
while (p!=lst.end()){
cout << *p << ' ';
p++;
}
_getch();
return 0;
}
Результат выполнения программы
Size of list = 10
Contents: 0 1 2 3 4 5 6 7 8 9
Modified contents: 100 101 102 103 104 105 106 107 108 109
Слайд 18Эта программа создаёт список целых чисел. Сначала формируется пустой список,
после чего в него с помощью push_back() записываются 10 целых
чисел, причём каждое записывается в конец существующего списка. После этого на экран выводится размер и содержимое этого списка. Затем каждое число увеличивается на 100 и снова выводятся на экран.
Важно обратить внимание на работу с итератором. Он намного удобнее и универсальнее указателя. При прибавлении единицы к текущему итератору мы получим следующий в контейнере объект независимо от типа элементов контейнера.
Функция end()
Во всех предыдущих примерах можно обратить внимание, что для "обхода" контейнера используется цикл с предусловием, а в качестве условия — неравенство итератора концу контейнера. Важное свойство функции end() - она возвращает указатель не на последний элемент контейнера, а на следующий за ним элемент. Таким образом, последнему элементу соответствует значение end() - 1. Это позволяет создавать очень эффективные алгоритмы обхода всех элементов контейнера, включая последний элемент. Если значение итератора становится равным значению end(), значит, все элементы контейнера пройдены. Эту особенность следует помнить всегда, чтобы избежать ошибок в использовании данной функции.
Слайд 19Ассоциативные контейнеры
Класс map создаёт ассоциативный контейнер, в котором каждому ключу
соответствует единственное значение. Сам ключ представляет собой имя, с помощью
которого можно получить требуемое значение. Если в контейнере хранится некоторое значение, доступ к нему возможен только через ключ. Таким образом, ассоциативный контейнер хранит пары "ключ-значение". Преимущество таких контейнеров — в доступе к значениям по ключам. К примеру, по имени или фамилии человека (ключ) можно узнать его номер телефона (значение).
Как указывалось ранее, map может содержать только уникальные ключи, дубликаты не допускаются. Если необходимо создать ассоциативный контейнер, который может хранить дубликаты, применяется класс multimap или multiset.
Шаблонная спецификация класса map имеет следующий вид:
template , class Allocator = allocator< pair > class map
Класс Key определяет тип ключа, шаблонный параметр Type задаёт тип данных, хранящихся в ассоциативном массиве, а функтор Comp позволяет сравнивать два ключа. По-умолчанию в качестве функции Comp применяется стандартный функтор less(). Распределитель задаётся классом Allocator.
Слайд 20Класс map имеет следующие конструкторы
explicit map(const Comp &cmpfn=Comp(), const Allocator
&a = Allocator());
map(const map &ob);
template
map (InIter start, InIter end, const Comp &cmpfn = Comp(), const Allocator &a = Allocator());
Первый конструктор создаёт пустой ассоциативный массив. Второй — контейнер, содержащий элементы объекта ob. Третий — создаёт массив, состоящий из элементов, лежащих в диапазоне, заданном итераторами start и end. Функция cmpfn определяет порядок следования элементов массива.
Как правило, любой объект, использующийся в качестве ключа, должен определять конструктор по-умолчанию, а так же операторы сравнения. Для каждого компилятора имеются свои требования к ключам.
В классе map определены следующие операторы сравнения:
==, <, <=, !=, >, >=
Функции-члены, определённые в этом классе перечислены в таблице ниже. Класс key_type представляет собой тип ключа, а класс value_type определяет тип pair
Слайд 22
Пары "ключ-значение" хранятся в ассоциативном массиве как объекты типа pair.