Різниця між std :: pair та std :: кортежем лише з двома членами?


92

Чи є різниця між a std::pairта an std::tupleлише з двома членами? (Окрім очевидного, що std::pairвимагає двох і лише двох членів і tupleможе мати більше або менше ...)

Відповіді:


86

Є деякі відмінності:

  1. std::tupleніколи не може бути за стандартним макетом (принаймні, це не обов’язково за стандартом). Кожен std::pair<T, Y>стандартний макет, якщо обидва Tі Yстандартний макет.

  2. Отримати вміст a, pairніж a tuple. У випадку потрібно використовувати виклик функції tuple, тоді як pairрегістр - це лише поле-член.

Але це все.


5
"Вибрати дані з пари трохи легше, ніж кортеж. Трохи". Я помітив. : P Хоча .firstі .secondє зручними, вони не надають допомоги, якщо для зміни коду потрібен третій (або більше) учасник (и). Я помітив, що, як правило, використовую std::getв будь-яких Getters, щоб мені не потрібно було змінювати все, лише типи даних та будь-які make_pairдзвінки на make_tupleдзвінки.
Casey

Схоже, що std::mapвикористовується std::pair<const Key,T>як value_typeпарне в C ++ 11. Де саме використовуються кортежі std::map?
nknight

@nknight: ... Я не уявляю, чому я це сказав. Або те, що я хотів сказати замість цього std::map.
Nicol Bolas

1
@Yakk: Гм, я натискаю "." і моя IDE пропонує список учасників. Я не думав, що людям потрібно це прописано.
Nicol Bolas

2
Цікаво, чи структуроване прив'язування в c ++ 17 вже робить недійсним і 1, і 2 пункти цієї відповіді? Якщо так, будь ласка, додайте версію цього файлу на c ++ 17.
піщанка

29

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

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


4
Звичайно, C ++ 20[[no_unique_address]] повинен усунути std::pairнедолік.
Deduplicator

"std :: кортеж дозволяє доступ лише через допоміжні функції" або структуровані прив'язки C ++ 17. Сумно, що так багато розумних відповідей на C ++ сьогодні так швидко застаріли. :-(
cosimo193

29

std::tupleІм'я «s більше (один додатковий символ). Більшість із цих символів набираються правою рукою, тому більшій людині набирати текст легше.

Тим не менш, std::pairможе мати лише два значення - не нуль, одне, три або більше. ДВІ значення. Проте кортеж майже не має семантичного обмеження на кількість значень. std::pairТаким чином, An є більш точним, безпечним для типу типом типом для використання, якщо ви насправді хочете вказати пару значень.


20
ЛОЛ! Чудово, що ви враховуєте, як його набирають! Хоча я хотів би зазначити, що я, мабуть, набираю "пару" більш ніж на 20% швидше, ніж "кортеж". Це тому, що мої руки набирають кожного символа по черзі, тобто. RHS: p, LHS: a, RHS: i, LHS: r. Принаймні для мене це легше зробити! - але ви все одно отримуєте +1!
Richard Corden,

15
" Отже, std :: pair - це більш точний тип безпечного типу, який слід використовувати, якщо ви дійсно хочете вказати пару значень. " Він не є більш безпечним для типу або "точним", він лише (можливо) сигналізує про намір більш безпосередньо.
ildjarn

1
@Arafangion: std::tuple<>немає також тіпобезопасним (як це могло не бути?), І 2це не семантично відрізняється pair.
ildjarn

1
" Отже, std :: pair - це більш точний, безпечний для використання тип ". І я думаю, що будь-хто, хто говорить англійською, буде вважати слова "пара" та "два" цілком синонімами. : -]
ildjarn

5
@ildjam: Ми тут розділяємо волосся, але ні, вони не є повністю синонімами. Коли ви говорите "два черевики", ви маєте на увазі "два черевики, які цілком можуть бути як лівими черевиками", чи ви маєте на увазі "пара взуття" (одне з яких завжди ліве, а інше завжди праве) ?
Arafangion

9

Зауважте, що в C ++ 17 можна використовувати один і той же інтерфейс для читання даних як з пари, так і з двома елементами.

auto [a, b] = FunctionToReturnPairOrTuple();

Не потрібно використовувати get<>:)


3

Наскільки це варте, мені здається, що вихід GDB std :: tuple набагато складніший для читання. Очевидно, якщо вам потрібно більше 2 значень, тоді std :: pair не буде працювати, але я вважаю це моментом на користь структур.


Ось чому, коли я використовував їх на заняттях, я обертаю валовий рядок std::get<0>(tupleName)у геттер; GetX()набагато легше для читання та коротше. Вона має невеликий недолік , що якщо ви забули зробити це constметод хто - то може зробити що - то дурне , як це: GetX() = 20;.
Кейсі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.