มีรูปภาพที่รู้จักกันดี (ข้อมูลโกง) ที่เรียกว่า "C ++ Container choice" เป็นผังงานเพื่อเลือกภาชนะที่ดีที่สุดสำหรับการใช้งานที่ต้องการ
มีใครรู้บ้างว่ามีเวอร์ชัน C ++ 11 อยู่แล้วหรือไม่?
นี่คือรายการก่อนหน้า:

มีรูปภาพที่รู้จักกันดี (ข้อมูลโกง) ที่เรียกว่า "C ++ Container choice" เป็นผังงานเพื่อเลือกภาชนะที่ดีที่สุดสำหรับการใช้งานที่ต้องการ
มีใครรู้บ้างว่ามีเวอร์ชัน C ++ 11 อยู่แล้วหรือไม่?
นี่คือรายการก่อนหน้า:

คำตอบ:
ไม่ใช่ว่าฉันรู้ แต่มันสามารถทำได้ตามข้อความฉันเดา นอกจากนี้แผนภูมิยังดับเล็กน้อยเนื่องจากlistโดยทั่วไปไม่ใช่คอนเทนเนอร์ที่ดีและไม่เป็นforward_listเช่นนั้น ทั้งสองรายการเป็นคอนเทนเนอร์พิเศษสำหรับการใช้งานเฉพาะกลุ่ม
ในการสร้างแผนภูมิดังกล่าวคุณต้องมีแนวทางง่ายๆสองข้อ:
การกังวลเกี่ยวกับประสิทธิภาพมักจะไร้ประโยชน์ในตอนแรก การพิจารณา O ครั้งใหญ่จะเกิดขึ้นเมื่อคุณเริ่มจัดการรายการไม่กี่พัน (หรือมากกว่า) เท่านั้น
ตู้คอนเทนเนอร์มีสองประเภทใหญ่ ๆ :
findดำเนินการstackและจากนั้นคุณสามารถสร้างอะแดปเตอร์หลายด้านบนของพวกเขา queue, priority_queue, ฉันจะทิ้งอะแดปเตอร์ไว้ที่นี่เนื่องจากมีความเชี่ยวชาญเพียงพอที่จะจดจำได้
คำถามที่ 1: Associative ?
คำถาม 1.1: สั่งซื้อ ?
unordered_คอนเทนเนอร์หรือใช้คำสั่งซื้อแบบดั้งเดิมคำถาม 1.2: แยกคีย์ ?
mapหรือใช้ asetคำถามที่ 1.3: ซ้ำกัน ?
multiมิฉะนั้นอย่าทำตัวอย่าง:
สมมติว่าฉันมีบุคคลหลายคนที่มี ID เฉพาะที่เกี่ยวข้องกับพวกเขาและฉันต้องการดึงข้อมูลบุคคลจาก ID ของบุคคลนั้นให้ง่ายที่สุด
ฉันต้องการfindฟังก์ชันจึงเป็นคอนเทนเนอร์ที่เชื่อมโยงกัน
1.1. ฉันไม่สนใจคำสั่งซื้อน้อยลงดังนั้นunordered_คอนเทนเนอร์
1.2. คีย์ (ID) ของฉันแยกจากค่าที่เกี่ยวข้องดังนั้นจึงเป็นmap
1.3. ID ไม่ซ้ำกันจึงไม่ควรเล็ดลอดเข้ามาซ้ำ
คำตอบสุดท้ายคือ: std::unordered_map<ID, PersonData>.
คำถามที่ 2: หน่วยความจำเสถียรหรือไม่?
listคำถาม 2.1: ไหน ?
list; a forward_listมีประโยชน์สำหรับหน่วยความจำที่น้อยลงเท่านั้นคำถามที่ 3: ขนาดแบบไดนามิก ?
{ ... }ไวยากรณ์) จากนั้นใช้array. แทนที่ C-array แบบเดิม แต่มีฟังก์ชันที่สะดวกคำถามที่ 4: Double-ended ?
dequeหรือใช้ a vector.vectorคุณจะทราบว่าโดยปกติถ้าคุณต้องการภาชนะที่สมาคมทางเลือกของคุณจะเป็น มันจะเปิดออกก็ยังเป็นซัทเทอและ Stroustrup ของคำแนะนำ
arrayไม่ต้องการประเภทที่สร้างได้เริ่มต้น 2) การเลือกรายการmultiนั้นไม่มากเกี่ยวกับการอนุญาตให้ทำซ้ำแต่ข้อมูลเพิ่มเติมเกี่ยวกับว่าการเก็บข้อมูลเหล่านี้มีความสำคัญหรือไม่ (คุณสามารถใส่รายการที่ซ้ำกันในmultiคอนเทนเนอร์ที่ไม่ใช่คอนเทนเนอร์ได้ แต่ก็เกิดขึ้นที่มีเพียงรายการเดียวเท่านั้นที่ถูกเก็บไว้)
                    map.find(key)เป็นที่พอใจมากขึ้นกว่าstd::find(map.begin(), map.end(), [&](decltype(map.front()) p) { return p.first < key; }));แต่ดังนั้นจึงเป็นสิ่งที่สำคัญความหมายว่าเป็นหน้าที่ของสมาชิกมากกว่าหนึ่งจากfind <algorithm>สำหรับ O (1) กับ O (log n) จะไม่มีผลต่อความหมาย ฉันจะลบ "ประสิทธิภาพ" ออกจากตัวอย่างและแทนที่ด้วย "อย่างง่ายดาย"
                    dequeมีคุณสมบัตินี้ด้วยเหรอ?
                    dequeองค์ประกอบจะคงที่ก็ต่อเมื่อคุณดัน / ป๊อปที่ปลายด้านใดด้านหนึ่ง หากคุณเริ่มแทรก / ลบตรงกลางองค์ประกอบสูงสุด N / 2 จะถูกสับเพื่อเติมช่องว่างที่สร้างขึ้น
                    ฉันชอบคำตอบของ Matthieu แต่ฉันจะสร้างผังงานใหม่เป็นดังนี้:
std::vectorโดยค่าเริ่มต้นถ้าคุณต้องการภาชนะของสิ่งที่ใช้ ดังนั้นคอนเทนเนอร์อื่น ๆ ทั้งหมดจึงมีเหตุผลโดยการให้ฟังก์ชันทางเลือกบางอย่างstd::vectorเท่านั้น
std::vectorต้องการให้เนื้อหาเคลื่อนย้ายได้เนื่องจากต้องสามารถสับเปลี่ยนรายการรอบ ๆ นี่ไม่ใช่ภาระที่น่ากลัวในการวางเนื้อหา (โปรดทราบว่าไม่จำเป็นต้องใช้ตัวสร้างเริ่มต้นขอบคุณemplaceและอื่น ๆ ) อย่างไรก็ตามคอนเทนเนอร์อื่น ๆ ส่วนใหญ่ไม่ต้องการตัวสร้างใด ๆ โดยเฉพาะ (ขอบคุณอีกครั้งemplace) ดังนั้นหากคุณมีวัตถุที่คุณไม่สามารถใช้ตัวสร้างการย้ายได้อย่างแน่นอนคุณจะต้องเลือกอย่างอื่น
A std::dequeจะเป็นการแทนที่ทั่วไปโดยมีคุณสมบัติมากมายstd::vectorแต่คุณสามารถแทรกที่ปลายด้านใดด้านหนึ่งของ deque เท่านั้น เม็ดมีดตรงกลางต้องการการเคลื่อนย้าย std::listสถานที่ต้องการไม่มีในเนื้อหา
std::vector<bool>ไม่ใช่. มันเป็นมาตรฐาน แต่มันไม่ใช่vectorในแง่ปกติเนื่องจากการดำเนินการที่std::vectorอนุญาตตามปกติเป็นสิ่งต้องห้าม และแน่นอนที่สุดไม่ได้มีbool s
ดังนั้นถ้าคุณต้องการจริงvectorพฤติกรรมจากภาชนะของbools std::vector<bool>คุณจะไม่ได้รับจาก ดังนั้นคุณจะต้องชำระเงินด้วยไฟล์std::deque<bool>.
หากคุณต้องการที่จะหาองค์ประกอบในภาชนะและแท็กค้นหาไม่สามารถเพียงแค่เป็นดัชนีแล้วคุณอาจต้องละทิ้งstd::vectorในความโปรดปรานของและset mapสังเกตคำสำคัญ " may "; std::vectorบางครั้งการเรียงลำดับก็เป็นทางเลือกที่สมเหตุสมผล หรือ Boost.Container ของซึ่งการดำเนินการเรียงลำดับflat_set/mapstd::vector
ตอนนี้มีสี่รูปแบบเหล่านี้แต่ละแบบมีความต้องการของตัวเอง
mapเมื่อแท็กค้นหาไม่ใช่สิ่งเดียวกับรายการที่คุณกำลังค้นหา มิฉะนั้นให้ใช้ไฟล์set.unorderedเมื่อคุณมีจำนวนมากของรายการในภาชนะและค้นหาประสิทธิภาพอย่างจะต้องมีมากกว่าO(1)O(logn)multiหากคุณต้องการหลายรายการเพื่อให้มีแท็กการค้นหาเดียวกันหากคุณต้องการให้มีการจัดเรียงตู้สินค้าตามการดำเนินการเปรียบเทียบโดยเฉพาะคุณสามารถใช้ไฟล์set. หรือmulti_setถ้าคุณต้องการหลายรายการเพื่อให้มีมูลค่าเท่ากัน
หรือคุณสามารถใช้การจัดเรียงstd::vectorแต่คุณจะต้องจัดเรียงไว้
เมื่อตัวทำซ้ำและการอ้างอิงไม่ถูกต้องบางครั้งก็เป็นเรื่องที่น่ากังวล หากคุณต้องการรายการที่คุณมีตัวทำซ้ำ / ตัวชี้ไปยังรายการเหล่านั้นในที่อื่น ๆstd::vectorวิธีการที่จะทำให้ไม่ถูกต้องอาจไม่เหมาะสม การดำเนินการแทรกใด ๆ อาจทำให้ไม่ถูกต้องขึ้นอยู่กับขนาดและความจุปัจจุบัน
std::listเสนอการรับประกันที่มั่นคง: ตัววนซ้ำและการอ้างอิง / ตัวชี้ที่เกี่ยวข้องจะไม่ถูกต้องก็ต่อเมื่อมีการนำไอเท็มออกจากคอนเทนเนอร์ std::forward_listจะมีไหมหากความทรงจำเป็นปัญหาร้ายแรง
หากการรับประกันนั้นแข็งแกร่งเกินไปให้เสนอการรับประกันstd::dequeที่อ่อนแอกว่า แต่มีประโยชน์ การไม่ตรวจสอบเป็นผลมาจากการแทรกที่อยู่ตรงกลาง แต่การแทรกที่ส่วนหัวหรือส่วนท้ายทำให้เกิดการไม่ถูกต้องของตัวทำซ้ำเท่านั้นไม่ใช่ตัวชี้ / การอ้างอิงไปยังรายการในคอนเทนเนอร์
std::vector ให้การแทรกราคาถูกในตอนท้ายเท่านั้น (และถึงแม้จะมีราคาแพงหากคุณเป่าความจุ)
std::listมีราคาแพงในแง่ของประสิทธิภาพ (แต่ละรายการแทรกใหม่ค่าใช้จ่ายในการจัดสรรหน่วยความจำ) แต่มันเป็นเรื่องที่สอดคล้องกัน นอกจากนี้ยังมีความสามารถที่ขาดไม่ได้ในบางครั้งในการสับเปลี่ยนไอเท็มรอบ ๆ โดยแทบจะไม่มีต้นทุนด้านประสิทธิภาพอีกทั้งยังสามารถแลกเปลี่ยนสินค้ากับstd::listคอนเทนเนอร์ประเภทเดียวกันได้โดยไม่สูญเสียประสิทธิภาพ หากคุณจำเป็นต้องสับเปลี่ยนสิ่งรอบ ๆจำนวนมากstd::listใช้
std::dequeให้การแทรก / ถอดที่หัวและท้ายตลอดเวลา แต่การแทรกตรงกลางอาจมีราคาแพงพอสมควร ดังนั้นหากคุณต้องการเพิ่ม / ลบสิ่งต่างๆจากด้านหน้าและด้านหลังstd::dequeอาจเป็นสิ่งที่คุณต้องการ
ควรสังเกตว่าด้วยการย้ายความหมายstd::vectorประสิทธิภาพการแทรกอาจไม่เลวร้ายอย่างที่เคยเป็น การใช้งานบางอย่างใช้รูปแบบของการคัดลอกรายการที่อิงตามความหมาย (หรือที่เรียกว่า "swaptimization") แต่ตอนนี้การย้ายนั้นเป็นส่วนหนึ่งของภาษามันได้รับคำสั่งจากมาตรฐาน
std::arrayเป็นคอนเทนเนอร์ที่ดีหากคุณต้องการการจัดสรรแบบไดนามิกน้อยที่สุดเท่าที่จะเป็นไปได้ มันเป็นเพียงกระดาษห่อหุ้มรอบ C-array ที่นี้หมายถึงว่าขนาดของมันจะต้องรู้จักที่รวบรวมเวลา std::arrayหากคุณสามารถอยู่กับที่แล้วใช้
ที่ถูกกล่าวว่าการใช้std::vectorและreserveไอเอ็นจีขนาดจะทำงานได้เป็นอย่างดีสำหรับ std::vectorbounded ด้วยวิธีนี้ขนาดจริงอาจแตกต่างกันไปและคุณจะได้รับการจัดสรรหน่วยความจำเพียงชุดเดียว (เว้นแต่คุณจะเพิ่มขีดความสามารถ)
std::sortนี้ยังมีสิ่งstd::inplace_mergeที่น่าสนใจในการวางองค์ประกอบใหม่ ๆ ได้อย่างง่ายดาย (แทนที่จะเป็นstd::lower_bound+ std::vector::insertโทร) ยินดีที่ได้เรียนรู้flat_setและflat_map!
                    vector<bool> vector<char>
                    std::allocator<T>ไม่รองรับการจัดแนวนั้น (และฉันไม่รู้ว่าทำไมจึงไม่) คุณสามารถใช้ตัวจัดสรรที่กำหนดเองได้ตลอดเวลา
                    std::vector::resizeมีโอเวอร์โหลดที่ไม่ใช้ค่า (ใช้ขนาดใหม่เท่านั้นองค์ประกอบใหม่ใด ๆ จะถูกสร้างขึ้นตามค่าเริ่มต้น) นอกจากนี้เหตุใดคอมไพเลอร์จึงไม่สามารถจัดแนวพารามิเตอร์ค่าได้อย่างถูกต้องแม้ว่าจะมีการประกาศว่ามีการจัดแนวก็ตาม
                    bitsetสำหรับบูลหากคุณทราบขนาดล่วงหน้าen.cppreference.com/w/cpp/utility/bitset
                    นี่คือผังงานด้านบนเวอร์ชัน C ++ 11 [โพสต์ครั้งแรกโดยไม่มีการระบุแหล่งที่มาของผู้เขียนต้นฉบับMikael Persson ]

นี่เป็นการหมุนอย่างรวดเร็วแม้ว่าอาจต้องใช้งาน
Should the container let you manage the order of the elements?
Yes:
  Will the container contain always exactly the same number of elements? 
  Yes:
    Does the container need a fast move operator?
    Yes: std::vector
    No: std::array
  No:
    Do you absolutely need stable iterators? (be certain!)
    Yes: boost::stable_vector (as a last case fallback, std::list)
    No: 
      Do inserts happen only at the ends?
      Yes: std::deque
      No: std::vector
No: 
  Are keys associated with Values?
  Yes:
    Do the keys need to be sorted?
    Yes: 
      Are there more than one value per key?
      Yes: boost::flat_map (as a last case fallback, std::map)
      No: boost::flat_multimap (as a last case fallback, std::map)
    No:
      Are there more than one value per key?
      Yes: std::unordered_multimap
      No: std::unordered_map
  No:
    Are elements read then removed in a certain order?
    Yes:
      Order is:
      Ordered by element: std::priority_queue
      First in First out: std::queue
      First in Last out: std::stack
      Other: Custom based on std::vector????? 
    No:
      Should the elements be sorted by value?
      Yes: boost::flat_set
      No: std::vector
คุณอาจพบว่ามีความแตกต่างอย่างดุเดือดจากซี ++ 03 รุ่นหลักเนื่องจากความจริงที่ว่าผมไม่ชอบโหนดที่เชื่อมโยง โดยปกติคอนเทนเนอร์โหนดที่เชื่อมโยงสามารถเอาชนะประสิทธิภาพได้โดยคอนเทนเนอร์ที่ไม่ได้เชื่อมโยงยกเว้นในบางสถานการณ์ที่เกิดขึ้นได้ยาก หากคุณไม่รู้ว่าสถานการณ์เหล่านั้นคืออะไรและสามารถเข้าถึงบูสต์ได้อย่าใช้คอนเทนเนอร์โหนดที่เชื่อมโยง (std :: list, std :: slist, std :: map, std :: multimap, std :: set, std :: multiset) รายการนี้เน้นที่คอนเทนเนอร์ขนาดเล็กและขนาดกลางเป็นส่วนใหญ่เนื่องจาก (A) เป็น 99.99% ของสิ่งที่เราจัดการในโค้ดและ (B) องค์ประกอบจำนวนมากต้องการอัลกอริทึมที่กำหนดเองไม่ใช่คอนเทนเนอร์ที่แตกต่าง