Что такое pair и где использовать?

219
19 декабря 2016, 19:45

Не могу понять зачем такое объединение двух объектов разного или одного типа, в один объект?
И чем это отличается от map?
И как или какой смысл использовать pair вместе с map?

Answer 1

Ну, мало ли зачем может понадобиться. Например, для того же std::map: когда итерируете по нему, текущим элементом является пара из ключа и значения, то есть соответственно std::pair<K, V>.

Ещё при помощи пары легко моделировать функцию, которая может вернуть, а может и не вернуть значение.

Пример:

template <typename T>
std::pair<bool, T> parse_string(const std::wstring &s)
{
    std::wistringstream iss(s);
    T t;
    bool success = !(iss >> t).fail();
    return std::make_pair(success, t);
}
auto r1 = parse_string<int>(L"123");
if (r1.first)
    cout << r.second;
else
    cout << "fail";

Или, например, функция двоичного поиска в отсортированном массиве. По-хорошему она должна возвращать не какой-то из найденных индексов, в все индексы, потому что элементы могут повторяться. Впрочем, такая функцию уже есть: std::equal_range возвращает именно std::pair из начального и конечного итераторов.

Функция целочисленного деления тоже по-хорошему должна возвращать пару из частного и остатка.

Для всех этих случаев заводить специальные структуры данных означало бы излишнюю захламлённость кода, и необходимость держать в голове десятки специальных типов данных, которые есть по существу не больше, чем пара объектов. C++ достаточно сложен и без этого.

Answer 2

std::map это контейнер, он эффективен только для достаточно большого количества данных ~ > 100. Использовать его для 1-2 значений не очень разумно.

Применение:

  • Хранить 2D клетку карты.
  • Хранить Координаты X и Y.
  • Хранить тип переменной для void*.
  • Если нужен индекс по двойному ключу. (имя-фамилия)

    std::map<std::string , std::map<std::string,досье>> персонал;
    персонал["Эл"]["Якобсон"].зарплата = 500000;
    //в данном случаи поиск ключа будет выполнятся 1 раз, что может положительно сказаться на производительности
    std::map<std::pair<std::string,std::string>,досье> персонал;
    персонал[std::pair<std::string,std::string>("Эл","Якобсон")].зарплата = 500000;
  • Вспомогательная переменная для определения действий(в дополнение к ответу VladD).

enum АВТОМОЙКА { ЛЕГКОВАЯ, ГРУЗОВАЯ, ГУМАНОИД };

std::pair<ТИП_ОБРАБОТКИ,std::string> объект = текущий_объект_на_ленте();
if(объект.first == ЛЕГКОВАЯ){ загрузить_программу_легковой(объект.second);}
if(объект.first == ГРУЗОВАЯ){ загрузить_программу_грузовой(объект.second);}
if(объект.first == ГУМАНОИД){ остановить_чистку(); удалить_объект(объект.second);}

Преимущества:

сравнение:

// для одиночных переменных
int X1;
int Y1;
int X2;
int Y2;
if(X1 == X2 && Y1 == Y2){} // выглядит не очень
// для pair
typedef std::pair<int , int> клетка;
клетка клетка_1;
клетка клетка_2;
if(клетка_1 == клетка_2){} // так более понятно

Компактность:

Если две переменные логически связаны, то создавать для этой связи новый тип(struct) слишком затратно.

struct товар
{
int ид;
std::string название;
operator==()
operator!=()
конструктор()
};
проще:
std::pair<int , std::string> товар;

Скорость:

std::pair<int , std::string> товар;
auto ид_товара = товар.ид; // доступ сразу
std::map<int , std::string> товар2;
auto ид_товара = товар2.begin()->first; // доступ через итератор

Память:

std::map выделяет память под разные внутренние конструкции(вспомогательные переменные)(это же к/ч дерево(или не совсем к/ч)). В debug режиме заметно снижает производительность и затрудняет отладку.

Тип пара, по идее имеет только два члена. И память выделяется только под них.

Например:

template<typename first_ , typename second_>
struct pair
{
first_ first;
second_ second;
};

Недостатки:

Рефакторинг будет затруднён:

Если вместо X,Y окажется что необходимо работать с X,Y,Z то будет не очень приятно. Придется писать свой тип трира. уже с 3 элементами или делать struct.

В то время как используя struct достаточно просто добавить int Z; и обновить методы этой структуры.

READ ALSO
Полиморфизм

Полиморфизм

Требуются помощь с реализацией трех задачДумаю над их реализацией больше недели

186
Присвоить значение элементу массива

Присвоить значение элементу массива

Только начал изучать С++, возникла сложностьНеобходимо присвоить определенному элементу массива значение

167
Генератор случайных чисел

Генератор случайных чисел

Не могу понять как заставить генератор случайных чисел давать дробные значенияПробовал сделать так

203