Разница между std :: pair и std :: tuple только с двумя членами?

92

Есть ли разница между an std::pairи an std::tupleтолько с двумя членами? (Помимо очевидного, что std::pairтребует двух и только двух членов и tupleможет иметь больше или меньше ...)

Кейси
источник

Ответы:

86

Есть некоторые отличия:

  1. std::tupleникогда не может быть стандартным (по крайней мере, стандартным не требуется ). Каждый std::pair<T, Y>является стандартным макетом , если оба Tи Yявляются стандартным макетом.

  2. Получить содержимое файла a немного проще, pairчем файла tuple. Вы должны использовать вызов функции в tupleслучае, в то время как pairслучай - это просто поле члена.

Но это все.

Никол Болас
источник
5
«Из пары получить данные немного проще, чем из кортежа. Немного». Я отметил. : P Хотя .firstи .secondудобны, они не предлагают никакой помощи, если для изменения кода требуется третий (или более) член (ы). Я заметил, что я обычно использую std::getнезависимо в любых геттерах, поэтому мне не нужно менять все, только типы данных и любые make_pairвызовы make_tupleвызовов.
Casey
Похоже, что std::mapиспользуется std::pair<const Key,T>как value_typeдаже в C ++ 11. Где именно используются кортежи std::map?
nknight 01
@nknight: ... Понятия не имею, почему я это сказал. Или то, что я хотел сказать вместо std::map.
Никол Болас
1
@Yakk: Гм, я нажимаю "." и моя IDE отображает список участников. Я не думал, что людям нужно это разъяснять.
Никол Болас
2
Интересно, если структурированная привязка в С ++ 17 уже делает недействительными как 1, так и 2 пункта этого ответа? Если да, пожалуйста, добавьте его версию для C ++ 17.
Sandthorn
29

Это очень поздний ответ, но обратите внимание, что, поскольку std::pairон определен с помощью переменных-членов, его размер не может быть оптимизирован с помощью оптимизации пустого базового класса ( firstи secondдолжен занимать разные адреса, даже если один или оба являются пустыми классами). Это усугубляется любыми требованиями к выравниванию second_type, поэтому в худшем случае результат std::pairбудет в два раза больше, чем должен быть.

std::tupleразрешает доступ только через вспомогательные функции, поэтому он может быть унаследован от любого типа, если один или другой пуст, что позволяет сэкономить на накладных расходах. Реализация ССЗ, по крайней мере, безусловно , делает это ... вы можете протыкать заголовки , чтобы убедиться в этом , но есть и это в качестве доказательства.

Стивен Лин
источник
4
Конечно, C ++ 20[[no_unique_address]] должен устранить этот std::pairнедостаток.
Дедупликатор
«std :: tuple разрешает доступ только через вспомогательные функции» или структурированные привязки C ++ 17. Печально, что так много разумных ответов на C ++ в наши дни так быстро устаревают. :-(
cosimo193
29

std::tupleИмя «s больше (один дополнительный символ). Больше этих символов набирается правой рукой, поэтому большинству людей легче набирать текст.

При этом std::pairможет иметь только два значения - не ноль, один, три или более. ДВА ценности. Однако кортеж почти не имеет семантических ограничений на количество значений. std::pair, Следовательно, является более точным, типобезопасен типом использовать , если вы действительно хотите , чтобы задать пару значений.

Арафангион
источник
20
ЛОЛ! Замечательно, что вы считаете, как это набирается! Однако я хотел бы отметить, что я, вероятно, набираю «пара» более чем на 20% быстрее, чем «кортеж». Это потому, что мои руки вводят каждый символ поочередно, т.е. RHS: p, LHS: a, RHS: i, LHS: r. По крайней мере, для меня это легче сделать! - но вы все равно получите +1!
Ричард Корден
15
« Таким образом, std :: pair является более точным типобезопасным типом, который можно использовать, если вы действительно хотите указать пару значений». Это не более типобезопасный или «точный» тип, он только (возможно) сигнализирует о намерении более прямо.
ildjarn 01
1
@Arafangion: std::tuple<>нет также типобезопасным (как это могло не быть?), И 2это не семантически отличается pair.
ildjarn 02
1
« Таким образом, std :: pair является более точным и безопасным по типу типом для использования ». И я думаю, что любой англоязычный человек сочтет «пара» и «два» полностью синонимами. : -]
ildjarn 02
5
@ildjam: Мы тут секем волосы, но нет, это не совсем синонимы. Когда вы говорите «две туфли», вы имеете в виду «две туфли, которые вполне могут быть как левые туфли», или вы имеете в виду «пару туфель» (одна из которых всегда левая, а другая всегда правая) ?
Арафангион
9

Обратите внимание, что в C ++ 17 можно использовать один и тот же интерфейс для чтения данных как из пары, так и из кортежа с двумя элементами.

auto [a, b] = FunctionToReturnPairOrTuple();

Не нужно использовать get<>:)

Bhardwajs
источник
3

Как бы то ни было, я считаю, что вывод std :: tuple GDB гораздо труднее читать. Очевидно, что если вам нужно более двух значений, то std :: pair не будет работать, но я считаю это аргументом в пользу структур.

Tgoodhart
источник
Вот почему, когда я использовал их в классах, я помещал строку брутто std::get<0>(tupleName)в геттер; GetX()намного легче читать и короче. Она имеет небольшой недостаток , что если вы забыли сделать это constметод кто - то может сделать что - то глупое , как это: GetX() = 20;.
Casey