Структура pair
Иногда удобно в одной переменной хранить одновременно два значения, например, два целых числа. Например, координаты точки на плоскости удобно хранить в одной переменной, содержащих два числа: x-координату и y-координату. Для этого в STL есть шаблон pair (пара), особенно удобно использовать pair для сортировки объектов.
Pair является переменной, объединяющей в себе два значения, которые могут быть одного или разных типов. Например, чтобы создать переменную типа pair, содержащую два поля типа int нужно использовать следующее объявление:
pair a;
Теперь переменная a будет хранить в себе два значения типа int . Получить доступ к первому значению можно при помощи записи a.first , а ко второму значению — a.second , они называются полями переменной. Каждому полю можно присваивать независимые значения, например, так:
a.first = 1; a.second = 2;
Присвоить одновременно два значения обоим полям пары можно при помощи функции make_pair , принимающующей два аргумента и возвращающей значение типа pair с соответствующими полями:
a = make_pair(1, 2);
Между тем с переменной типа pair можно работать и как с единым целым, например, если объявить две переменные типа pair с одинаковыми типами полей, то можно одной переменной присвоить значение другой переменной:
pair a, b; . b = a;
Но при вводе-выводе переменных, типа pair нельзя выводить или вводить значение переменной одной командой, то есть нельзя сразу же вывести два значения типа:
cin >> a; coutВместо этого нужно отдельно считывать или выводить каждое поле пары.
Можно создавать пару с полями разных типов, например, чтобы поле first имело тип double , а поле second — string , нужно использовать запись pair .
С парой, как с целым (то есть одновременно с двумя полями структуры) можно выполнять следующие операции: = , == , != , < , , >= , а также использовать в качестве аргумента функции swap . При использовании операций сравнения (типа меньше, больше и т.д.) пары сравниваются в лексикографическом порядке, то есть сначала по полю first , а если поля first равны, то по полю second .
vector < pair< int, int>> aОбратите внимание на пробел между закрывающими угловыми скобками: он обязателен, иначе компилятор будет считать это операцией “ >> ”
Make pair c что это
На этом шаге мы рассмотрим использование функции make_pair .
Шаблонная функция make_pair() позволяет создать пару значений без явного указания типов:
namespace std < // Создание обьекта пары только по значениям template class T1, class T2> pair make_pair(const T1& x, const T2& y) < return pair(x, y); > >Замечание . Использование функции make_pair() не требует дополнительных затрат при выполнении программы. Компилятор всегда оптимизирует подобные вызовы.
Например, благодаря функции make_pair следующие строки эквивалентны:
std::make_pair(42,'@') std::pair(42,'@')В частности, функция make_pair позволяет легко передать два значения, образующие пару, функции с аргументом типа pair . Рассмотрим следующий пример:
void f(std::pair); void g(std::pairconst int,std::string>); . . . . void foo < f(std::make_pair(42,"hello")); // Два значения передаются в виде пары g(std::make_pair(42,"hello")); // Два значения передаются в виде пары // с преобразованием типа. >Как видно из приведенного примера, функция make_pair() упрощает передачу двух значений в одном аргументе. Она работает даже при неполном соответствии типов, поскольку шаблонный конструктор обеспечивает автоматическое преобразование. Такая возможность особенно часто используется при работе с отображениями и мультиотображениями.
Впрочем, у выражений с явным указанием типов есть свое преимущество - они четко определяют тип полученной пары. Например, следующие два выражения дают разные результаты:
std::pair(42,7.77) std::make_pair(42,7.77)Во втором случае создается объект pair , у которого второй компонент относится к типу double (вещественные литералы с неуточненным типом интерпретируются как double ). Тип может оказаться существенным при использовании перегруженных функций или шаблонов, в которых, например, для повышения эффективности могут быть предусмотрены разные версии для float и double .
На следующем шаге мы начнем знакомиться с классом auto_ptr .
STL
Вспомогательные компоненты
В заголовочном файле
определены шаблоны функций для operator!= из operator== и operator>, = из operator (для использования шаблонов написать using namespace std::rel_ops;). Также
включает шаблон класса для разнородных пар значений pair . Для этого типа определены операции == и <. Для создания пары используется функция make_pair(5, 3.1415926). Класс tuple (кортеж) является аналогом pair для неограниченного числа значений и определен в . Для доступа к элементам кортежа используется функция std::get `i` > (нумерация с 0). Для извлечения всех значений из кортежа используется функция tie (для ненужных полей указывается ignore). Для создания кортежа используется функции make_tuple и forward_as_tuple (кортеж из ссылок на временные значения). Функция tuple_cat позволяет соединить несколько кортежей в один.
tupleint,char,double> t1(10,'x',1.0),t2; get(t2)=get(t1); t2=make_tuple(1,'b',2.0); int x; double y; tie(x,ignore,y)=t2; print(forward_as_tuple("Name"s,10)); . void print(tupleint&&> arg) < cout<
Функциональные объекты – это объекты, для которых определён operator(). Они важны для эффективного использования библиотеки. В местах, где ожидается передача указателя на функцию алгоритмическому шаблону, интерфейс установлен на приём объекта с определённым operator(). Это не только заставляет алгоритмические шаблоны работать с указателями на функции, но также позволяет им работать с произвольными функциональными объектами. Использование функциональных объектов вместе с шаблонами функций увеличивает выразительную мощность библиотеки также, как делает результирующий код более эффективным. Например, если мы хотим поэлементно сложить два вектора a и b, содержащие double, и поместить результат в a, мы можем сделать это так: transform(a.begin(), a.end(), b.begin(), a.begin(), plusdouble>());В заголовочном файле
определены функционалы plus, minus, times, divides, modulus, negate, equal_to, not_equal_to, less, greater, less_equal, greater_equal, logical_or, logical_and, logical_not. Пользователь может производить свои функционалы, наследуя от unary_function и binary_function и определяя operator(). Можно превращать бинарные функционалы в унарные с помощью связывателей bind1st и bind2nd, заменяющих соответствующий аргумент на константу: bind2nd(less(),40) (значение меньше 40). Структура pair
Структура, позволяющая обрабатывать два объекта как один объект.
Синтаксис
struct pair < typedef T1 first_type; typedef T2 second_type; T1 first; T2 second; constexpr pair(); pair(const pair&) = default; pair(pair&&) = default; constexpr pair( const T1& Val1, const T2& Val2); template constexpr pair(const pair& Right); template constexpr pair(const pair && Right); template constexpr pair(Other1&& Val1, Other2&& Val2); template pair(piecewise_construct_t, tuple first_args, tuple second_args); pair& operator=(const pair& p); template pair& operator=(const pair& p); pair& operator=(pair&& p) noexcept(see below ); template pair& operator=(pair&& p); void swap(pair& p) noexcept(see below ); >; template pair(T1, T2) -> pair;Параметры
Val1
Значение, которое инициализирует первый элемент pair .Val2
Значение, которое инициализирует второй элемент pair .Right
Пара, значения которой будут использоваться для инициализации элементов другой пары.Возвращаемое значение
Первый конструктор (по умолчанию) инициализирует первый элемент пары по умолчанию и второй элемент по умолчанию T1 типа T2 . Определяется, если оба типа являются конструкцией по умолчанию.
Второй конструктор инициализирует первый элемент пары в Val1 , а второй — Val2. Он определяется, если оба типа являются скопируемыми.
Третий конструктор (шаблон) инициализирует первый элемент пары Right в . первый и второй — Right . second. Он определяется, если оба типа пары создаются из указанных типов значений.
Четвертый конструктор инициализирует первый элемент пары в Val1, а второй — Val2 с помощью декларатора ссылки Rvalue: && Он определяется, если оба типа пары создаются из указанных типов значений.
Замечания
Структура шаблона сохраняет пару объектов типа T1 и T2 соответственно. Тип first_type совпадает с параметром T1 шаблона, а тип second_type совпадает с параметром T2 шаблона. T1 и T2 каждому нужно предоставить только конструктор по умолчанию, конструктор с одним аргументом и деструктор. Все члены типа pair являются общедоступными, так как тип объявляется как не struct как . class Два наиболее распространенных способа применения пары — в качестве возвращаемых типов для функций, возвращающих два значения, и в качестве элементов для классов ассоциативных контейнеров map и multimap, у которых есть ключ и тип значения, связанные с каждым элементом. Последний удовлетворяет требованиям для пары ассоциативный контейнер и имеет тип значения формы pair < const key_type, mapped_type >.
Пример
// utility_pair.cpp // compile with: /EHsc #include #include #include #include int main( ) < using namespace std; // Using the constructor to declare and initialize a pair pair p1 ( 10, 1.1e-2 ); // Compare using the helper function to declare and initialize a pair pair p2; p2 = make_pair ( 10, 2.22e-1 ); // Making a copy of a pair pair p3 ( p1 ); cout.precision ( 3 ); cout m1; map ::iterator m1_Iter; typedef pair Map_Int_Pair; m1.insert ( Map_Int_Pair ( 1, 10 ) ); m1.insert ( Map_Int_Pair ( 2, 20 ) ); m1.insert ( Map_Int_Pair ( 3, 30 ) ); cout first second ::iterator, bool > pr1, pr2; pr1 = m1.insert ( Map_Int_Pair ( 4, 40 ) ); pr2 = m1.insert ( Map_Int_Pair (1, 10 ) ); if( pr1.second == true ) < cout else < cout first ) = " first if( pr2.second == true ) < cout else < cout first ) = " first >The pair p1 is: ( 10, 0.011 ). The pair p2 is: ( 10, 0.222 ). The pair p3 is: ( 10, 0.011 ). The element pairs of the map m1 are: ( 1, 10 ) ( 2, 20 ) ( 3, 30 ). The element (4,40) was inserted successfully in m1. The element with a key value of ( (pr2.first) -> first ) = 1 is already in m1, so the insertion failed.
STL