ความแตกต่างระหว่าง 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. ง่ายกว่าเล็กน้อยที่จะรับเนื้อหาของpairไฟล์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 tuples ใช้ในที่ไหนกันแน่std::map?
nknight

@nknight: ... ฉันไม่รู้ว่าทำไมฉันถึงพูดแบบนั้น std::mapหรือสิ่งที่ฉันหมายถึงว่าแทน
Nicol Bolas

1
@ ยัค: อืมฉันกด "." และ IDE ของฉันจะแสดงรายชื่อสมาชิก ฉันไม่คิดว่าผู้คนต้องการสิ่งนั้น
Nicol Bolas

2
ฉันสงสัยว่าการผูกแบบมีโครงสร้างใน c ++ 17 แล้วทำให้ทั้ง 1 และ 2 ของคำตอบนี้ไม่ถูกต้องหรือไม่? ถ้าเป็นเช่นนั้นโปรดเพิ่ม c ++ 17 เวอร์ชันนี้ด้วย
sandthorn

29

นี่เป็นคำตอบที่ล่าช้ามาก แต่โปรดทราบว่าเนื่องจากstd::pairกำหนดด้วยตัวแปรสมาชิกจึงไม่สามารถปรับขนาดให้เหมาะสมโดยใช้การเพิ่มประสิทธิภาพคลาสพื้นฐานที่ว่างเปล่า ( firstและsecondต้องใช้ที่อยู่ที่แตกต่างกันแม้ว่าหนึ่งหรือทั้งสองจะเป็นคลาสว่างก็ตาม) สิ่งนี้เลวร้ายลงเนื่องจากข้อกำหนดในการจัดตำแหน่งใดก็ตามที่second_typeมีดังนั้นในกรณีที่เลวร้ายที่สุดผลลัพธ์std::pairจะมีขนาดเป็นสองเท่าของขนาดที่ต้องการ

std::tupleอนุญาตให้เข้าถึงผ่านฟังก์ชันตัวช่วยเท่านั้นดังนั้นจึงเป็นไปได้ที่จะได้มาจากประเภทใดประเภทหนึ่งถ้าอย่างใดอย่างหนึ่งว่างเปล่าโดยประหยัดค่าใช้จ่าย อย่างน้อยการใช้งาน GCC ก็ทำได้อย่างแน่นอน ... คุณสามารถโผล่ส่วนหัวเพื่อตรวจสอบสิ่งนี้ได้ แต่ก็มีสิ่งนี้เป็นหลักฐานด้วย


4
แน่นอนC ++ 20[[no_unique_address]]ควรลบstd::pairข้อเสีย
Deduplicator

"std :: tuple อนุญาตให้เข้าถึงผ่านฟังก์ชันตัวช่วยเท่านั้น" หรือการเชื่อมโยงที่มีโครงสร้าง C ++ 17 น่าเศร้าที่คำตอบ C ++ ที่สมเหตุสมผลจำนวนมากล้าสมัยไปอย่างรวดเร็วในทุกวันนี้ :-(
cosimo193

29

std::tupleชื่อมีความยาว (ตัวละครตัวหนึ่งเป็นพิเศษ) อักขระเหล่านี้พิมพ์ด้วยมือขวาจำนวนมากขึ้นเพื่อให้คนส่วนใหญ่พิมพ์ได้ง่ายขึ้น

ที่กล่าวว่าstd::pairสามารถมีได้เพียงสองค่า - ไม่ใช่ศูนย์หนึ่งสามหรือมากกว่า สองค่า อย่างไรก็ตามทูเปิลแทบไม่มีข้อ จำกัด เชิงความหมายเกี่ยวกับจำนวนค่า std::pairจึงเป็นความถูกต้องแม่นยำมากขึ้นพิมพ์ชนิดปลอดภัยในการใช้งานถ้าคุณต้องการจริงเพื่อระบุคู่ของค่า


20
ฮ่า ๆ! ยอดเยี่ยมที่คุณพิจารณาว่ามันพิมพ์อย่างไร! ฉันอยากจะชี้ให้เห็นว่าฉันอาจจะพิมพ์ 'คู่' เร็วกว่า 'ทูเปิล' มากกว่า 20% นี่เป็นเพราะมือของฉันพิมพ์อักขระแต่ละตัวอีกทางหนึ่งเช่น RHS: p, LHS: a, RHS: i, LHS: r. อย่างน้อยสำหรับฉันฉันคิดว่ามันง่ายกว่าที่จะทำ! - แต่คุณยังได้รับ +1!
Richard Corden

15
" ดังนั้นคู่ std :: จึงเป็นประเภทปลอดภัยที่แม่นยำกว่าที่จะใช้หากคุณต้องการระบุคู่ค่าจริงๆ " ไม่ใช่ประเภทที่ปลอดภัยกว่าหรือ "ถูกต้อง" แต่เป็นสัญญาณเจตนา (เนื้อหา) เท่านั้น โดยตรงมากขึ้น
ildjarn

1
@Arafangion: std::tuple<>เป็นยังพิมพ์ปลอดภัย (ว่ามันอาจจะไม่?) และจะไม่มีความหมายที่แตกต่างกันมากกว่า2 pair
ildjarn

1
" ดังนั้นคู่มาตรฐาน :: จึงเป็นประเภทที่ปลอดภัยและแม่นยำกว่าที่จะใช้ " และฉันคิดว่าผู้พูดภาษาอังกฤษทุกคนจะคิดว่า "คู่" และ "สอง" มีความหมายเหมือนกันทั้งหมด : -]
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;
Casey
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.