Читать интересную книгу "Язык программирования C++. Пятое издание - Стенли Липпман"

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 141 142 143 144 145 146 147 148 149 ... 297

Здесь для определения типа оператора используется спецификатор decltype. При использовании спецификатора decltype для получения указателя на функцию следует добавить символ * для обозначения использования указателя на заданный тип функции (см. раздел 6.7). Инициализацию bookstore осуществляет функция compareIsbn(). Это означает, что при добавлении элементов в bookstore они будут упорядочены при вызове функции compareIsbn(). Таким образом, элементы bookstore будут упорядочены по их члену ISBN. Аргумент конструктора можно записать как compareIsbn, вместо &compareIsbn, поскольку при использовании имени функции оно автоматически преобразуется в указатель, если это нужно (см. раздел 6.7). С тем же результатом можно написать &compareIsbn.

Упражнения раздела 11.2.2

Упражнение 11.9. Определите карту, которая ассоциирует слова со списком номеров строк, в которых оно встречается.

Упражнение 11.10. Можно ли определить карту для типов vector<int>::iterator и int? А для типов list<int>::iterator и int? Если нет, то почему?

Упражнение 11.11. Переопределите bookstore, не используя спецификатор decltype.

11.2.3. Тип pair

Прежде чем перейти к рассмотрению действий с ассоциативными контейнерами, имеет смысл ознакомиться с библиотечным типом pair (пара), определенным в заголовке utility.

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

pair<string, string> anon;       // содержит две строки

pair<string, size_t> word_count; // содержит строку и целое число

pair<string, vector<int>> line;  // содержит строку и vector<int>

При создании объекта пары без указания инициализирующих значений используются стандартные конструкторы типов его переменных-членов. Таким образом, пара anon содержит две пустые строки, а пара line — пустую строку и пустой вектор целых чисел. Значением переменной-члена типа int в паре word_count будет 0, а его переменная-член типа string окажется инициализирована пустой строкой.

Можно также предоставить инициализаторы для каждого члена пары:

pair<string, string> author{"James", "Joyce"};

Этот код создает пару по имени author, инициализированную значениями "James" и "Joyce".

В отличие от других библиотечных типов, переменные-члены класса pair являются открытыми (см. раздел 7.2). Эти члены — first (первый) и second (второй) соответственно. К ним можно обращаться непосредственно, используя обычный точечный оператор (см. раздел 1.5.2), как, например, было сделано в операторе вывода программы подсчета слов в разделе 11.1:

// отобразить результаты

cout << w.first << " occurs " << w.second

     << ((w.second > 1) ? " times" : " time") << endl;

где w — ссылка на элемент карты. Элементами карты являются пары. В данном операторе выводится переменная-член first элемента, являющаяся ключом, затем переменная-член second элемента, являющаяся счетчиком. Библиотека определяет весьма ограниченный набор операций с парами, который приведен в табл. 11.2.

Таблица 11.2. Операции с парами

pair<T1, T2> p; p — пара с переменными-членами типов T1 и T2, инициализированными значением по умолчанию (см. раздел 3.3.1) pair<T1, T2> р(v1, v2); p — пара с переменными-членами типов T1 и T2, инициализированными значениями v1 и v2 соответственно pair<T1, T2> р = {v1, v2}; Эквивалент p(v1, v2) make_pair(v1, v2) Возвращает пару, инициализированную значениями v1 и v2. Тип пары выводится из типов значений v1 и v2 p.first Возвращает открытую переменную-член first пары p p.second Возвращает открытую переменную-член second пары p p1 опсравн p2 Операторы сравнения (<, >, <=, >=). Сравнение осуществляется подобно упорядочиванию в словаре, т.е. оператор < возвращает значение true в случае, если p1.first < p2.first или !(p2.first < p1.first) && p1.second < p2.second p1 == p2, p1 != p2 Две пары равны, если их первый и второй члены соответственно равны. При сравнении используется оператор == хранимых элементов Функция для создания объектов типа pair

Предположим, некая функция должна возвратить значение типа pair. По новому стандарту возможна списочная инициализация возвращаемого значения (см. раздел 6.3.2):

pair<string, int>

process(vector<string> &v) {

 // обработка v

 if (!v.empty())

  return {v.back(), v.back().size()}; // списочная инициализация

 else

  return pair<string, int>(); // возвращаемое значение создано явно

}

Если вектор v не пуст, возвращается пара, состоящая из последней строки в векторе v и размера этой строки. В противном случае явно создается и возвращается пустая пара.

В прежних версиях языка С++ нельзя было использовать инициализаторы в скобках для возвращения типа, подобного pair. Вместо этого можно было написать оба оператора return как явно созданное возвращаемое значение:

if (!v.empty())

 return pair<string, int>(v.back(), v.back().size());

В качестве альтернативы можно использовать функцию make_pair() для создания новой пары соответствующего типа из двух аргументов:

if (!v.empty())

 return make_pair(v.back(), v.back().size());

Упражнения раздела 11.2.3

Упражнение 11.12. Напишите программу, читающую последовательность строк и целых чисел, сохраняя каждую прочитанную пару в объекте класса pair. Сохраните пары в векторе.

Упражнение 11.13. Существует по крайней мере три способа создания пар в программе предыдущего упражнения. Напишите три версии программы, создающей пары каждым из этих способов. Укажите, какая из форм проще и почему.

Упражнение 11.14. Дополните карту фамилий семей и их детей, написанную для упражнения в разделе 11.2.1, вектором пар, содержащих имя ребенка и день его рождения.

11.3. Работа с ассоциативными контейнерами

В дополнение к типам, перечисленным в табл. 9.2 (стр. 423), ассоциативные контейнеры определяют типы, перечисленные в табл. 11.3. Они представляют типы ключа и значения контейнера.

Таблица 11.3. Псевдонимы дополнительных типов ассоциативных контейнеров

key_type Тип ключа контейнера mapped_type Тип, ассоциированный с каждым ключом; только для типа map value_type Для наборов то же, что и key_type. Для карт — pair<const key_type, mapped type>

Для контейнеров типа set типы key_type и value_type совпадают; содержащиеся в наборе данные являются ключами. Элементами карты являются пары ключ-значение. Таким образом, каждый ее элемент — объект класса pair, содержащий ключ и связанное с ним значение. Поскольку ключ элемента изменить нельзя, ключевая часть этих пар константна:

set<string>::value_type v1;       // v1 - string

set<string>::key_type v2;         // v2 - string

map<string, int>::value_type v3;  // v3 - pair<const string, int>

map<string, int>::key_type v4;    // v4 - string

map<string, int>::mapped_type v5; // v5 - int

Подобно последовательным контейнерам (см. раздел 9.2.2), для доступа к члену класса, например типа map<string, int>::key_type, используется оператор области видимости.

Тип mapped_type определен только для типов карт (unordered_map, unordered_multimap, multimap и map).

1 ... 141 142 143 144 145 146 147 148 149 ... 297
Прочитали эту книгу? Оставьте комментарий - нам важно ваше мнение! Поделитесь впечатлениями и помогите другим читателям сделать выбор.

Оставить комментарий