Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
LectionSTL3.doc
Скачиваний:
0
Добавлен:
12.11.2019
Размер:
367.62 Кб
Скачать

Контейнеры STL

Контейнеры STL делятся на два больших семейства – контейнеры последовательностей (или просто последовательные контейнеры) и отсортированные ассоциативные контейнеры.

Контейнеры последовательностей включают векторы, списки и деки, которые содержат элементы одного типа в строгом линейном порядке. Хотя в библиотеке представлены только три базовых контейнера последовательностей, можно эффективно создавать другие контейнеры последовательностей на основе базовых благодаря применению адаптеров контейнеров, которые представляют собой классы STL, обеспечивающие отображение интерфейсов. Библиотека STL предоставляет адаптеры для стеков, очередей и очередей с приоритетами. Отсортированные ассоциативные контейнеры включают множества, мультимножества, отображения и мультиотображения. Ассоциативные контейнеры обеспечивают быструю выборку данных на основе ключей. Например, отображение позволяет пользователю получить объект типа Т на основе ключа некоторого другого типа; множества позволяют быстро получать сами ключи.

Все контейнеры STL обладают следующими важными характеристиками:

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

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

  3. Включает несколько определений типов typedef, создающий стандартный для всех набор имен типов и интерфейс работы с алгоритмами:

::value_type – тип значений T, хранящийся в контейнере;

::reference – ссылка на объект (&T), хранящийся в контейнере;

::pointer – тип указателя на объект (*T), хранящийся в контейнере;

::const_pointer – тип константного указателя на объект, хранящийся в контейнере;

::const_reference – константная ссылка на объект;

::iterator – тип итератора для обхода элементов в контейнере;

::const_iterator – тип итератора для обхода элементов в константном контейнере;

::reverse_iterator – тип итератора для обхода контейнера в обратном направлении;

::const_reverse_iterator – тип итератора для обхода константного контейнера в обратном направлении;

::size_type – размер типа объекта, находящегося в контейнере;

::difference_type – тип, представляющий расстояние между двумя объектами итераторов контейнера.

  1. Все контейнеры имеют конструктор по умолчанию (создает пустой контейнер), конструктор копирования, деструктор (освобождает всю память, использованную контейнером, и вызывает деструктор каждого элемента в контейнере).

  2. Поддерживают следующие операции над контейнерами: =, ==, <, <=, >, >=, !=.

  3. Включают следующие функции-методы:

iterator begin() – возвращает итератор, указывающий на начало (первый элемент) контейнера;

const_iterator begin()const – возвращает константный итератор, указывающий на начало (первый элемент) контейнера;

iterator end() – возвращает итератор, указывающий на позицию, следующую за последним элементом контейнера;

const_iterator end()const – возвращает константный итератор, указывающий на позицию, следующую за последним элементом контейнера;

reverse_iterator rbegin() – возвращает обратный итератор, указывающий на последний элемент контейнера;

const_reverse_iterator rbegin()const – возвращает константный обратный итератор, указывающий на последний элемент контейнера;

reverse_iterator rend() – возвращает обратный итератор, указывающий на позицию, предшествующую первому элементу контейнера;

const_reverse_iterator rend()const – возвращает константный обратный итератор, указывающий на позицию, предшествующую первому элементу контейнера;

bool empty() const – возвращает true если контейнер пуст;

void swap(Container Type c) – обменивает между собой содержимое двух контейнеров;

size_type size()const – возвращает количество элементов, в текущий момент хранящийся в контейнере;

size_type max_size()const – возвращает максимальное количество элементов, которые может хранить контейнер;

void clear() – удаляет все элементы из контейнера.

Последовательные контейнеры STL

В дополнение к выше перечисленным функциям-методам, все контейнеры последовательностей реализуют следующие методы:

  1. Два дополнительных конструктора, первый из которых в качестве аргументов принимает величины size_type num и const T &val и создает последовательность, содержащую num копий величин val; второй конструктор в качестве аргументов принимает два входных итератора InputItr first, InputItr last, который конструирует последовательность, содержащую элементы из диапазона [first,last).

  2. Включают следующие функции-методы:

  1. Функции-методы для вставки элементов:

iterator insert(iterator i, const T &val) – вставляет копию val перед позицией, на которую указывает итератор i, возвращает итератор, указывающий на вставленный элемент;

void insert(iterator i, size_type num, const T &val) – вставляет num копий элемента val непосредственно перед позицией, на которую указывает итератор i;

void insert(iterator i, InputItr first, InputItr Last) – вставляет последовательность из диапазона [first,last)непосредственно перед позицией, на которую указывает итератор i. Итераторы first и last не должны быть итераторами контейнера, вызывающего данный метод;

void push_back(const T &val) – вставляет копию val в конец последовательности.

  1. Функции-методы для удаления элементов из последовательности:

iterator erase(iterator i) – удаляет элемент, на который указывает итератор i, возвращает итератор, указывающий на элемент, расположенный после удаленного.

iterator erase(iterator first, iterator last) – удаляет элементы из диапазона [first,last), возвращает итератор, указывающий на элемент, расположенный после последнего удаленного (на который указывал last до удаления).

void pop_back()– удаляет последний элемент последовательности. Результат не определен, если последовательность пуста.

  1. Функции-методы для обращения к элементам последовательности:

reference front(); const_reference front() const – возвращают первый элемент последовательности (элемент, на который указывает итератор begin() и rbegin()) .

reference back(); const_reference back() const – возвращают последний элемент последовательности (элемент, на который указывает итератор end()-1 и rend()-1) .

void resize(size_type sz, T val=T()) – изменяет размер последовательности до sz элементов, либо вставляя копии val, либо удаляя элементы с конца последовательности.

void assign(InputItr first, InputItr Last) – заменяет все содержимое последовательности, вызвавшего данную функцию, значениями из последовательности диапазона [first,last). При этом размер контейнера будет равен last – first.

void assign(size_type sz, const T &val) – удаляет любые элементы, ранее содержавшиеся в контейнере, и вместо них присваивает sz копий значения val.

Мы рассмотрели общие операции для всех последовательных контейнеров. Однако, в дополнение к общим методам, каждый последовательный контейнер поддерживает свои уникальные методы. Теперь мы перейдем к изучению всех трех типов последовательных контейнеров.

Важно!!! Необходимыми условиями хранения объектов в контейнерах STL являются следующие:

  1. Обязательное наличие в классе общедоступных методов: конструктора по умолчанию, конструктора копирования, деструктора и операции присваивания;

  2. В некоторых случаях общедоступную функцию operator==(), а если требуется упорядочивание то и функцию operator<().

При демонстрации работы с контейнерами будем использовать следующий класс:

class inventory

{

private:

char item[12];

double cost;

int quantity;

static int count;

public:

inventory();

inventory(const char* name,double s, int n);

inventory(const inventory &src);

~inventory();

inventory& operator=(const inventory &rhs);

static int getcount();

friend bool operator ==(const inventory &a1, const inventory &a2);

friend std::ostream & operator<<(std::ostream &stream, const inventory &obj);

friend std::istream & operator>>(std::istream &stream, inventory &obj);

};

Все поля и методы данного класса определены в приложении.

Контейнер vector

Векторы представляют собой контейнеры, которые располагают элементы данного типа в строгом линейном порядке и обеспечивают

  1. быстрый произвольный доступ к любому элементу (обращение к любому элементу происходит за константное время);

  2. вставку и удаление элементов в конец последовательности за амортизированное константное время;

  3. вставку и удаление элементов в начало или середину последовательности за линейное время.

По перечисленным свойствам видно, что вектор это динамический массив, снабженный функциями-методами:

begin()

end()

Двойная стрелка влево/вправо 3

Кроме выше перечисленных методов контейнер vector дополнен следующими методами:

reference operator[ ](size_type n);

const_reference operator[ ](size_type n)const – возвращает n-ый с начала вектора элемент за константное время;

reference at(size_type n);

const_reference at(size_type n)const – возвращает n-ый с начала вектора элемент за константное время после проверки границ вектора. Генерирует исключение, если в качестве аргумента передается n>=size();

size_type capacity()const – возвращает максимальное количество элементов, которые вектор может хранить без перераспределения памяти;

void reserve(size_type n) – директива, информирующая вектор о планируемом изменении размера, с тем чтобы можно было выполнить соответствующий запрос памяти. Этот вызов не изменяет размер вектора, а время его работы не более чем линейно зависит от размера вектора. Перераспределение памяти при вызове выполняется тогда и только тогда, когда текущая емкость (capacity) вектора меньше переданного аргумента (capacity — функция-член вектора, возвращающая размер выделенной для вектора памяти). После вызова reserve емкость становится не менее переданного функции-члену аргумента, если перераспределение состоялось, и остается неизменной в противном случае.

Перераспределение делает недействительными все ссылки, указатели и итераторы, указывающие на элементы вектора. Гарантируется, что после вызова reserve в процессе вставок в вектор перераспределения памяти не будут выполняться до тех пор, пока размер вектора не достигнет размера, указанного в аргументе reserve.

Все функции вставки вызывают перераспределение памяти, если новый размер вектора оказывается больше чем его старая емкость. Если перераспределение не выполняется, то все итераторы и ссылки, указывающие на элементы до точки вставки, остаются корректными. Для практических целей лучше предположить, что итераторы и ссылки не действительны после вставок. Функция erase делает недействительными все итераторы и ссылки после точки удаления.

Для работы с данным контейнером следует подключить дополнительную библиотеку: #include<vector>.

Рассмотрим примеры создания контейнера вектор.

std::vector<inventory> vector1;

При этом создается контейнер нулевого размера и нулевой емкости, т.е. методы vector1.size() и vector1.capacity()возвратят нулевое значение. Никаких объектов типа inventory не создается. Далее мы можем добавлять элементы в контейнер:

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]