Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


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



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

Помимо заголовков, требуемых различными классами STL, стандартная библиотека C++ включает заголовки < utility> и < functional> , которые обеспечивают поддержку STL. Например, в заголовке < utility> определяется шаблонный класс pair, который может хранить пару значений. Мы будем использовать класс pair ниже в этой главе.

Шаблоны в заголовке < functional> позволяют создавать объекты, которые определяют функцию operator(). Эти объекты называются объектами-функциями, и их во многих случаях можно использовать вместо указателей на функции. Существует несколько встроенных объектов-функций, объявленных в заголовке < functional> . Приведем здесь некоторые из них.

Возможно, наиболее широко используется объект-функция less, который определяет, при каких условиях один объект меньше другого. Объекты-функции можно использовать вместо реальных указателей на функции в алгоритмах STL, о которых пойдет речь ниже. Используя объекты-функции вместо указателей на функции, библиотека STL в некоторых случаях генерирует более эффективный программный код.

Материал этой главы не предусматривает использования объектов-функций, и мы не будем применять их напрямую. (Подробное описание объектов-функций можно найти в моей книге Полный справочник по C++, 4-е издание, М.: Издательский дом " Вильямс".)

Контейнерные классы

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

Поскольку имена типов в объявлениях шаблонных классов произвольны, контейнерные классы объявляют typedef-версии этих типов, что конкретизирует имена типов. Некоторые из наиболее популярных typedef-имен приведены ниже.

Поскольку в одной главе невозможно рассмотреть все контейнеры, в следующих разделах мы представим только три из них: vector, list и map. Если вы поймете, как работают эти три контейнера, у вас не будет проблем с использованием остальных.

Векторы

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

Одним из контейнеров самого широкого назначения является вектор. Класс vector поддерживает динамический массив, который при необходимости может увеличивать свой размер. Как вы знаете, в C++ размер массива фиксируется во время компиляции. И хотя это самый эффективный способ реализации массивов, он в то же время является и самым ограничивающим, поскольку размер массива нельзя изменять во время выполнения программы. Эта проблема решается с помощью вектора, который по мере необходимости обеспечивает выделение дополнительного объема памяти. Несмотря на то что вектор — это динамический массив, тем не менее, для доступа к его элементам можно использовать стандартное обозначение индексации массивов.

Вот как выглядит шаблонная спецификация для класса vector:

template < class Т, class Allocator = allocator< T> > class vector

Здесь T— тип сохраняемых данных, а элемент Allocator означает распределитель памяти, который по умолчанию использует стандартный распределитель. Класс vector имеет следующие конструкторы.

explicit vector(const Allocator & a = Allocator());

explicit vector(size_type num, const T & val = T(), const Allocator & a = Allocator());

vector(const vector< T, Allocator> & ob);

template < class InIter> vector(InIter start, InIter end, const Allocator & a = Allocator());

Первая форма конструктора предназначена для создания пустого вектора. Вторая создает вектор, который содержит num элементов со значением val, причем значение val может быть установлено по умолчанию. Третья форма позволяет создать вектор, который содержит те же элементы, что и заданный вектор ob. Четвертая предназначена для создания вектора, который содержит элементы в диапазоне, заданном параметрами-итераторами start и end.

Ради достижения максимальной гибкости и переносимости любой объект, который предназначен для хранения в векторе, должен определяться конструктором по умолчанию. Кроме того, он должен определять операции " < " и " ==" Некоторые компиляторы могут потребовать определения и других операторов сравнения. (В виду существования различных реализаций для получения точной информации о требованиях, предъявляемых вашим компилятором, следует обратиться к прилагаемой к нему документации.) Все встроенные типы автоматически удовлетворяют этим требованиям.

Несмотря на то что приведенный выше синтаксис шаблона выглядит довольно " массивно", в объявлении вектора нет ничего сложного. Рассмотрим несколько примеров.

vector< int> iv; /* Создание вектора нулевой длины для хранения int-значений. */

vector< char> cv(5); /* Создание 5-элементного вектора для хранения char-значений. */

vector< char> cv(5, 'х'); /* Инициализация 5-элементного char-вектора. */

vector< int> iv2(iv); /* Создание int-вектора на основе int-вектора iv. */

Для класса vector определены следующие операторы сравнения:

==, <, < =, ! =, > и > =

Для вектора также определен оператор индексации " []" , который позволяет получить доступ к элементам вектора с помощью стандартной записи с использованием индексов. Функции-члены, определенные в классе vector, перечислены в табл. 21.2. Самыми важными из них являются size(), begin(), end(), push_back(), insert() и erase(). Очень полезна функция size(), которая возвращает текущий размер вектора, поскольку она позволяет определить размер вектора во время выполнения программы. Помните, что векторы при необходимости увеличивают свой размер, поэтому нужно иметь возможность определять его величину во время работы программы, а не только во время компиляции.

Функция begin() возвращает итератор, который указывает на начало вектора. Функция end() возвращает итератор, который указывает на конец вектора. Как уже разъяснялось, итераторы подобны указателям, и с помощью функций begin() и end() можно получить итераторы для начала и конца вектора соответственно.

Функция push_back() помещает заданное значение в конец вектора. При необходимости длина вектора увеличивается так, чтобы он мог принять новый элемент. С помощью функции insert() можно добавлять элементы в середину вектора. Кроме того, вектор можно инициализировать. В любом случае, если вектор содержит элементы, то для доступа к ним и их модификации можно использовать средство индексации массивов. А с помощью функции erase() можно удалять элементы из вектора.

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

// Демонстрация базового поведения вектора.

#include < iostream>

#include < vector>

using namespace std;

Int main()

{

  vector< int> v; // создание вектора нулевой длины

  unsigned int i;

  // Отображаем исходный размер вектора v.

  cout < < " Размер = " < < v.size() < < endl;

  /* Помещаем значения в конец вектора, и размер вектора будет по необходимости увеличиваться. */

  for(i=0; i< 10; i++) v.push_back(i);

  // Отображаем текущий размер вектора v.

  cout < < " Текущее содержимое: ";

  cout < < " Новый размер = " < < v.size() < < endl;

  // Отображаем содержимое вектора.

  for(i=0; i< v.size(); i++) cout < < v[i] < < " ";

  cout < < endl;

  /* Помещаем в конец вектора новые значения, и размер вектора будет по необходимости увеличиваться. */

  for(i=0; i< 10; i++ ) v.push_back(i+10);

  // Отображаем текущий размер вектора v.

  cout < < " Новый размер = " < < v.size() < < endl;

  // Отображаем содержимое вектора.

  cout < < " Текущее содержимое: ";

  for(i=0; i< v.size(); i++) cout < < v[i] < < " ";

  cout < < endl;

  // Изменяем содержимое вектора.

  for(i=0; i< v.size(); i++) v[i] = v[i] + v[i];

  // Отображаем содержимое вектора.

  cout < < " Содержимое удвоено: ";

  for(i=0; i< v.size(); i++) cout < < v[i] < < " ";

  cout < < endl;

  return 0;

}


Поделиться:



Популярное:

Последнее изменение этой страницы: 2016-03-17; Просмотров: 1359; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.02 с.)
Главная | Случайная страница | Обратная связь