В C ++ 11 вы можете почти полностью обойтись без make_pair. Смотри мой ответ .
PlagueHammer
2
В C ++ 17 std::make_pairэто избыточно. Ниже приведен ответ, который детализирует это.
Дрю Дорманн
Ответы:
165
Разница в том, что std::pairвам нужно указать типы обоих элементов, тогда как std::make_pairвы создадите пару с типом элементов, которые ему передаются, без необходимости сообщать об этом. Это то, что я мог бы собрать из разных документов в любом случае.
На самом деле, типы должны быть выведены во время компиляции без необходимости указывать.
Чад
@ Да, я знаю, как использовать их оба, мне было просто любопытно, была ли причина для этого std::make_pair. Видимо это просто для удобства.
@Jay Это будет выглядеть так.
Тор Валамо
15
Я думаю, что вы можете сделать в one = {10, 20}настоящее время, но у меня нет под рукой компилятора C ++ 11, чтобы проверить это.
MSalters
6
Также обратите внимание, что make_pairработает с безымянными типами, включая структуры, союзы, лямбды и другие дуды.
Mooing Duck
35
Как ответил @MSalters выше, теперь вы можете использовать фигурные скобки, чтобы сделать это в C ++ 11 (только что проверил это с помощью компилятора C ++ 11):
«C ++ 17 делает возможным такой синтаксис и, следовательно, делает make_pair избыточным». - Почему это std::make_pairне стало устаревшим в C ++ 17?
Андре
@andreee Я не уверен, возможная причина в том, что это не создает проблем, поэтому не нужно ломать старый код? Но я не знаком с обоснованием комитета C ++, пинг меня, если вы найдете что-то.
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
1
Одна полезная вещь, с которой я столкнулся, это то, что возможность указывать типы с помощью std :: make_pair <T1, T2> (o1, o2) предотвращает ошибку пользователя при передаче типов o1 или o2, которые не могут быть явно приведение к T1 или T2. Например, передача отрицательного числа в целое число без знака. -Wsign-преобразование -Werror не будет ловить эту ошибку с помощью конструктора std :: pair в c ++ 11, однако она будет ловить ошибку, если используется std :: make_pair.
Конхоэсия
make_pairразворачивает справочные оболочки, поэтому на самом деле он отличается от CTAD.
LF
26
Нет разницы между использованием make_pairи явным вызовом pairконструктора с указанными аргументами типа. std::make_pairболее удобно, когда типы являются многословными, потому что метод шаблона имеет дедукцию типа на основе его заданных параметров. Например,
Стоит отметить, что это распространенная идиома в программировании на C ++. Он известен как идиома Object Generator, вы можете найти больше информации и хороший пример здесь .
редактировать Как кто-то предложил в комментариях (так как удалено), следующее является слегка измененной выдержкой из ссылки в случае ее разрыва.
Генератор объектов позволяет создавать объекты без явного указания их типов. Он основан на полезном свойстве шаблонов функций, которого нет в шаблонах классов: параметры типа шаблона функции автоматически определяются из его фактических параметров. std::make_pairпростой пример, который возвращает экземпляр std::pairшаблона в зависимости от фактических параметров std::make_pairфункции.
make_pair создает дополнительную копию над прямым конструктором. Я всегда печатаю свои пары, чтобы обеспечить простой синтаксис.
Это показывает разницу (пример Rampal Chaudhary):
Я уверен, что дополнительная копия будет исключена во всех случаях, если настройки оптимизации компилятора достаточно высоки.
Björn Pollex
1
Зачем вам когда-либо полагаться на оптимизацию компилятора для правильности?
SJBX
Я получаю одинаковые результаты с обеими версиями, и std::moveтолько внутри insertи / или вокруг того, на что будет ссылаться sample. Только когда я изменяю std::map<int,Sample>на std::map<int,Sample const&>это, я уменьшаю количество созданных объектов, и только когда я удаляю конструктор копирования, я удаляю все копии (очевидно). После внесения обоих этих изменений мой результат включает один вызов конструктора по умолчанию и два вызова деструктора для одного и того же объекта. Я думаю, что я что-то упускаю. (g ++ 5.4.1, c ++ 11)
Джон П
Я согласен с тем, что оптимизация и корректность должны быть полностью независимыми, поскольку именно такой код вы пишете в качестве проверки работоспособности после того, как разные уровни оптимизации дают противоречивые результаты. В общем, я бы порекомендовал emplaceвместо того, insertчтобы просто создавать значение для немедленной вставки (и вам не нужны дополнительные экземпляры). Это не моя область знаний, если я могу даже сказать, что она у меня есть, а копирование / перемещение Семантика, представленная в C ++ 11, очень мне помогла.
Джон П
Я полагаю, что столкнулся с точно такой же проблемой, и после отладки в течение всего вечера я наконец пришел сюда.
lllllllllllll
1
начиная с c ++ 11 просто используйте равномерную инициализацию для пар. Так что вместо:
{1, 2}может использоваться для инициализации пары, но не фиксирует тип пары. Т.е. при использовании авто вы должны взять на себя обязательство типа на РИТ: auto p = std::pair{"Tokyo"s, 9.00};.
std::make_pair
это избыточно. Ниже приведен ответ, который детализирует это.Ответы:
Разница в том, что
std::pair
вам нужно указать типы обоих элементов, тогда какstd::make_pair
вы создадите пару с типом элементов, которые ему передаются, без необходимости сообщать об этом. Это то, что я мог бы собрать из разных документов в любом случае.Посмотрите этот пример на http://www.cplusplus.com/reference/std/utility/make_pair/.
Помимо неявного бонуса за конвертацию, если бы вы не использовали make_pair, вам пришлось бы делать
каждый раз, когда вы назначаете один, что будет раздражать со временем ...
источник
std::make_pair
. Видимо это просто для удобства.one = {10, 20}
настоящее время, но у меня нет под рукой компилятора C ++ 11, чтобы проверить это.make_pair
работает с безымянными типами, включая структуры, союзы, лямбды и другие дуды.Как ответил @MSalters выше, теперь вы можете использовать фигурные скобки, чтобы сделать это в C ++ 11 (только что проверил это с помощью компилятора C ++ 11):
источник
Аргументы шаблона класса не могут быть выведены из конструктора до C ++ 17
До C ++ 17 вы не могли написать что-то вроде:
поскольку это будет выводить типы шаблонов из аргументов конструктора.
C ++ 17 делает возможным такой синтаксис и, следовательно,
make_pair
избыточным.До C ++ 17
std::make_pair
разрешалось писать меньше подробного кода:вместо более многословного:
который повторяет типы и может быть очень длинным.
Вывод типа работает в этом случае до C ++ 17, потому что
make_pair
не является конструктором.make_pair
по существу эквивалентно:Та же концепция относится к
inserter
противinsert_iterator
.Смотрите также:
Минимальный пример
Чтобы сделать вещи более конкретными, мы можем наблюдать проблему минимально с:
main.cpp
затем:
компилирует счастливо, но:
не удается с:
и требует вместо того, чтобы работать:
или помощник:
который использует обычную функцию вместо конструктора.
Разница для `std :: reference_wrapper
Этот комментарий упоминает, что
std::make_pair
разворачиваетstd::reference_wrapper
а конструктор - нет, так что это одно отличие. Пример TODO.Протестировано с GCC 8.1.0, Ubuntu 16.04 .
источник
std::make_pair
не стало устаревшим в C ++ 17?make_pair
разворачивает справочные оболочки, поэтому на самом деле он отличается от CTAD.Нет разницы между использованием
make_pair
и явным вызовомpair
конструктора с указанными аргументами типа.std::make_pair
более удобно, когда типы являются многословными, потому что метод шаблона имеет дедукцию типа на основе его заданных параметров. Например,источник
Стоит отметить, что это распространенная идиома в программировании на C ++. Он известен как идиома Object Generator, вы можете найти больше информации и хороший пример здесь .
редактировать Как кто-то предложил в комментариях (так как удалено), следующее является слегка измененной выдержкой из ссылки в случае ее разрыва.
Генератор объектов позволяет создавать объекты без явного указания их типов. Он основан на полезном свойстве шаблонов функций, которого нет в шаблонах классов: параметры типа шаблона функции автоматически определяются из его фактических параметров.
std::make_pair
простой пример, который возвращает экземплярstd::pair
шаблона в зависимости от фактических параметровstd::make_pair
функции.источник
&&
начиная с C ++ 11.make_pair создает дополнительную копию над прямым конструктором. Я всегда печатаю свои пары, чтобы обеспечить простой синтаксис.
Это показывает разницу (пример Rampal Chaudhary):
источник
std::move
только внутриinsert
и / или вокруг того, на что будет ссылатьсяsample
. Только когда я изменяюstd::map<int,Sample>
наstd::map<int,Sample const&>
это, я уменьшаю количество созданных объектов, и только когда я удаляю конструктор копирования, я удаляю все копии (очевидно). После внесения обоих этих изменений мой результат включает один вызов конструктора по умолчанию и два вызова деструктора для одного и того же объекта. Я думаю, что я что-то упускаю. (g ++ 5.4.1, c ++ 11)emplace
вместо того,insert
чтобы просто создавать значение для немедленной вставки (и вам не нужны дополнительные экземпляры). Это не моя область знаний, если я могу даже сказать, что она у меня есть, а копирование / перемещение Семантика, представленная в C ++ 11, очень мне помогла.начиная с c ++ 11 просто используйте равномерную инициализацию для пар. Так что вместо:
или
просто используйте
источник
{1, 2}
может использоваться для инициализации пары, но не фиксирует тип пары. Т.е. при использовании авто вы должны взять на себя обязательство типа на РИТ:auto p = std::pair{"Tokyo"s, 9.00};
.