Sự khác biệt giữa std :: pair và std :: tuple chỉ có hai thành viên?


92

Có sự khác biệt giữa an std::pairvà an std::tuplechỉ có hai thành viên không? (Bên cạnh điều hiển nhiên là std::pairyêu cầu hai và chỉ hai thành viên và tuplecó thể có nhiều hơn hoặc ít hơn ...)

Câu trả lời:


86

Có một số khác biệt:

  1. std::tuplekhông bao giờ có thể theo bố cục tiêu chuẩn (ít nhất, nó không bắt buộc phải theo tiêu chuẩn). Mọi std::pair<T, Y>là bố cục tiêu chuẩn nếu cả hai TYđều là bố cục tiêu chuẩn.

  2. Nó dễ dàng hơn một chút để lấy nội dung của a pairhơn a tuple. Bạn phải sử dụng một lời gọi hàm trong tupletrường hợp, trong khi pairtrường hợp chỉ là một trường thành viên.

Nhưng đó là về nó.


5
"Lấy dữ liệu ra khỏi một cặp dễ dàng hơn một chút. Một chút." Tôi nhận thấy. : P Mặc dù .first.secondtiện dụng, nhưng họ không giúp gì nếu (các) thành viên thứ ba (hoặc nhiều hơn) được yêu cầu thay đổi mã. Tôi nhận thấy rằng tôi có xu hướng sử dụng std::getbất kể trong bất kỳ Getters nào theo cách đó tôi không cần thay đổi mọi thứ, chỉ là các kiểu dữ liệu và bất kỳ make_pairlệnh gọi nào make_tuple.
Casey

Nó dường như std::mapsử dụng std::pair<const Key,T>như là value_typechẵn trong C ++ 11. Chính xác thì các bộ giá trị được sử dụng ở std::mapđâu?
nknight

@nknight: ... Tôi không hiểu tại sao tôi lại nói như vậy. Hoặc những gì tôi muốn nói thay vì std::map.
Nicol Bolas

1
@Yakk: Ừm, tôi nhấn "." và IDE của tôi đưa ra một danh sách các thành viên. Tôi không nghĩ rằng mọi người cần chính tả đó.
Nicol Bolas

2
Tôi tự hỏi liệu ràng buộc có cấu trúc trong c ++ 17 đã làm mất hiệu lực của cả điểm 1 và 2 của câu trả lời này chưa? Nếu vậy, vui lòng thêm phiên bản c ++ 17 của cái này.
sandthorn

29

Đây là một câu trả lời rất muộn nhưng lưu ý rằng, vì std::pairđược định nghĩa với các biến thành viên, kích thước của nó không thể được tối ưu hóa bằng cách sử dụng tối ưu hóa lớp cơ sở trống ( firstsecondphải chiếm các địa chỉ riêng biệt, ngay cả khi một hoặc cả hai là một lớp trống). Điều này càng trở nên trầm trọng hơn bởi bất kỳ yêu cầu căn chỉnh second_typenào, vì vậy trong trường hợp xấu nhất, kết quả std::pairvề cơ bản sẽ gấp đôi kích thước mà nó cần.

std::tuplechỉ cho phép truy cập thông qua các chức năng trợ giúp, vì vậy nó có thể bắt nguồn từ một trong hai loại nếu một hoặc loại kia trống, tiết kiệm chi phí. Việc triển khai của GCC, ít nhất, chắc chắn làm được điều này ... bạn có thể xem qua các tiêu đề để xác minh điều này nhưng cũng có đây là bằng chứng.


4
Tất nhiên, C ++ 20[[no_unique_address]] nên loại bỏ std::pairnhược điểm của.
Deduplicator

"std :: tuple chỉ cho phép truy cập thông qua các hàm trợ giúp", hoặc các liên kết có cấu trúc C ++ 17. Đáng buồn là rất nhiều câu trả lời C ++ hợp lý đã quá nhanh chóng lỗi thời trong những ngày này. :-(
cosimo193

29

std::tupleTên của An dài hơn (thêm một ký tự). Nhiều ký tự trong số đó được nhập bằng tay phải, vì vậy hầu hết mọi người đều dễ dàng nhập hơn.

Điều đó nói rằng, std::pairchỉ có thể có hai giá trị - không phải 0, một, ba hoặc nhiều hơn. HAI giá trị. Tuy nhiên, một tuple hầu như không có giới hạn ngữ nghĩa về số lượng giá trị. std::pairDo đó, An là kiểu an toàn, chính xác hơn để sử dụng nếu bạn thực sự muốn chỉ định một cặp giá trị.


20
CƯỜI LỚN! Tuyệt vời mà bạn xem xét cách nó được đánh máy! Tôi muốn chỉ ra rằng tôi có thể gõ 'cặp' nhanh hơn 20% so với 'tuple'. Điều này là do tay tôi gõ từng ký tự khác nhau, tức là. RHS: p, LHS: a, RHS: i, LHS: r. Ít nhất đối với tôi, tôi thấy điều đó dễ làm hơn! - nhưng bạn vẫn nhận được +1!
Richard Corden

15
" Vì vậy, một cặp std :: là loại an toàn chính xác hơn, để sử dụng nếu bạn thực sự muốn chỉ định một cặp giá trị. " Nó không phải là loại an toàn hơn hoặc "chính xác", nó chỉ (có thể cho là) ​​báo hiệu ý định trực tiếp hơn.
ildjarn

1
@Arafangion: cũngstd::tuple<> là kiểu an toàn (làm sao mà không được?), Và không khác về mặt ngữ nghĩa . 2pair
ildjarn

1
" Vì vậy, " std :: pair "là loại chính xác hơn, loại an toàn để sử dụng " Và tôi nghĩ rằng bất kỳ người nói tiếng Anh nào cũng sẽ nghĩ về 'pair` và' two 'là hoàn toàn đồng nghĩa. : -]
ildjarn

5
@ildjam: Chúng tôi đang chia nhỏ các sợi tóc ở đây, nhưng không, chúng không hoàn toàn đồng nghĩa. Khi bạn nói "hai chiếc giày", bạn có nghĩa là "Hai chiếc giày, có thể là cả đôi giày bên trái" hay bạn có nghĩa là "Một đôi giày" (Một trong số đó luôn bên trái và chiếc còn lại luôn đi đúng) ?
Arafangion

9

Lưu ý rằng với C ++ 17, người ta có thể sử dụng cùng một giao diện để đọc dữ liệu từ cả cặp và bộ với hai phần tử.

auto [a, b] = FunctionToReturnPairOrTuple();

Không cần sử dụng get<>:)


3

Đối với những gì nó đáng giá, tôi thấy đầu ra GDB của std :: tuple khó đọc hơn nhiều. Rõ ràng nếu bạn cần nhiều hơn 2 giá trị thì std :: pair sẽ không hoạt động, nhưng tôi coi đây là một điểm có lợi cho cấu trúc.


Đó là lý do tại sao khi tôi sử dụng chúng trong các lớp học, tôi gói gọn dòng tổng std::get<0>(tupleName)trong một getter; GetX()dễ đọc hơn và ngắn hơn rất nhiều. Nó có một nhược điểm nhỏ là nếu bạn quên làm cho nó một constphương pháp ai đó có thể làm điều gì đó ngu ngốc như thế này: GetX() = 20;.
Casey
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.