Что такое std:: pair?

Что такое std::pair, почему я должен использовать его и какие преимущества приносит boost::compressed_pair?

Ответ 1

std::pair - это тип данных для группировки двух значений вместе как один объект. std::map использует его для пар ключей, значений.

Пока вы изучаете pair, вы можете проверить tuple. Это похоже на pair, но для группировки произвольного числа значений. tuple является частью TR1, и многие компиляторы уже включают его с реализацией стандартной библиотеки.

Также обратите внимание на главу 1 "Кортежи" книги "Стандартные расширения библиотек С++: учебное пособие и ссылки" Пит Беккера, ISBN-13: 9780321412997, для подробного объяснения.

alt text http://ak.buy.com/db_assets/prod_images/225/202452225.jpg

Ответ 2

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

Итак, даже если у вас

struct A { };

A размер не будет равен 0, потому что тогда:

A a1;
A a2;
&a1 == &a2;

будет удерживаться, что не допускается.

Но многие компиляторы будут делать так называемую "пустую оптимизацию базового класса":

struct A { };
struct B { int x; };
struct C : public A { int x; };

Здесь отлично, если B и C имеют одинаковый размер, даже если sizeof(A) не может быть нулем.

Итак, boost::compressed_pair использует эту оптимизацию и по возможности наследует от одного или другого из типов в паре, если она пуста.

Значит, std::pair может выглядеть (я очень сильно ушел, ctors и т.д.):

template<typename FirstType, typename SecondType>
struct pair {
   FirstType first;
   SecondType second;
};

Это означает, что если FirstType или SecondType A, ваш pair<A, int> должен быть больше sizeof(int).

Но если вы используете compressed_pair, его сгенерированный код будет выглядеть схоже с:

 struct compressed_pair<A,int> : private A {
    int second_;
    A first() { return *this; }
    int second() { return second_; }
 };

И compressed_pair<A,int> будет только размером sizeof (int).

Ответ 3

Иногда вам нужно вернуть 2 значения из функции, и она часто переполняется, чтобы идти и создавать класс именно для этого.

std: пара пригодится в этих случаях.

Я думаю, что boost: compress_pair способен оптимизировать членов размером 0. Это в основном полезно для тяжелых шаблонных машин в библиотеках.

Если вы контролируете типы напрямую, это не имеет значения.

Ответ 4

Звучит странно, если вы услышите, что сжатый_pair заботится о нескольких байтах. Но на самом деле это может быть важно, если учесть, где может использоваться сжатый_pair. Например, рассмотрим этот код:

boost::function<void(int)> f(boost::bind(&f, _1));

Это может сильно повлиять на использование compress_pair в таких случаях, как описано выше. Что может произойти, если boost:: bind хранит указатель на функцию и место-держатель _1 как сам по себе или сам по себе std::pair? Ну, он может раздуваться до sizeof(&f) + sizeof(_1). Предполагая, что указатель на функцию имеет 8 байтов (это не редкость особенно для функций-членов), а у заполнителя есть один байт (см. Ответ Logan для почему), тогда нам понадобилось бы 9 байтов для объекта bind. Из-за выравнивания это может раздуваться до 12 байтов на обычной 32-битной системе.

boost::function поощряет его реализации применять небольшую оптимизацию объектов. Это означает, что для небольших функторов для хранения функтора используется небольшой буфер, непосредственно встроенный в объект boost::function. Для больших функторов куча должна использоваться с использованием оператора new для получения памяти. Вокруг boost версия 1.34 было принято решение эта оптимизация, потому что было показано, что можно получить очень большие преимущества в производительности.

Теперь разумный (но, возможно, еще довольно небольшой) предел для такого маленького буфера будет 8 байтов. То есть наш довольно простой объект привязки не будет помещаться в небольшой буфер и потребует сохранения нового оператора. Если объект привязки выше использовал бы compressed_pair, он может фактически уменьшить его размер до 8 байтов (или 4 байта для указателя функции нечлена), потому что placeholder - не более чем пустой объект.

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

Ответ 5

std:: пара подходит для пары других классов контейнеров в STL.

Например:

std::map<>
std::multimap<> 

Оба хранилища std:: пары ключей и значений.

При использовании карты и мультимапа вы часто обращаетесь к элементам с помощью указателя на пару.

Ответ 6

Это стандартный класс для хранения пары значений. Он возвращался/использовался некоторыми стандартными функциями, такими как std::map::insert.

boost::compressed_pair утверждает, что он более эффективен: см. здесь

Ответ 7

Дополнительная информация: boost:: compress_pair полезна, когда один из типов пар - это пустая структура. Это часто используется в метапрограммировании шаблонов, когда типы пар программно выводятся из других типов. В конце вы обычно имеете некоторую форму "пустой структуры".

Я предпочел бы std:: pair для любого "нормального" использования, если вы не используете метапрограммирование тяжелого шаблона.

Ответ 8

Это не что иное, как структура с двумя переменными под капотом.

Мне действительно не нравится использование std:: pair для возврата функции. Читателю кода нужно было бы знать, что такое первый. И второй.

Компромисс, который я иногда использую, заключается в том, чтобы немедленно создавать постоянные ссылки на .first и .second, при этом ясно указывая ссылки.

Ответ 9

Что такое std:: pair for, зачем использовать его?

Так же просто два элемента кортежа. Он был определен в первой версии STL в тех случаях, когда компиляторы не поддерживали широко поддерживающие шаблоны и методы метапрограммирования, которые потребовались бы для внедрения более сложных тип кортежа, например Boost.Tuple.

Это полезно во многих ситуациях. std::pair используется в стандартных ассоциативных контейнерах. Его можно использовать как простую форму диапазона std::pair<iterator, iterator> - поэтому можно определить алгоритмы, принимающие один объект, представляющий диапазон, вместо двух итераторов отдельно. (Это полезная альтернатива во многих ситуациях.)

Ответ 10

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