ตั้งแต่
- ทั้งคู่เป็นคอนเทนเนอร์หน่วยความจำที่ต่อเนื่องกัน
- คุณลักษณะที่ชาญฉลาด deque มีเวกเตอร์เกือบทุกอย่าง แต่มีมากกว่านั้นเนื่องจากการแทรกที่ด้านหน้ามีประสิทธิภาพ
ทำไมทุกคน Whould ต้องการstd::vectorเพื่อstd::deque?
ตั้งแต่
ทำไมทุกคน Whould ต้องการstd::vectorเพื่อstd::deque?
คำตอบ:
องค์ประกอบในdequeมีความไม่ต่อเนื่องกันในหน่วยความจำ vectorองค์ประกอบได้รับการประกันว่าเป็น ดังนั้นหากคุณต้องการที่จะมีปฏิสัมพันธ์กับห้องสมุด C ธรรมดาที่ต้องการอาร์เรย์ที่ต่อเนื่องกันหรือถ้าคุณสนใจ (มาก) vectorเกี่ยวกับท้องที่อวกาศแล้วคุณอาจจะชอบ นอกจากนี้เนื่องจากมีการทำบัญชีพิเศษบางหน่วยงานอื่น ๆ อาจมีราคาแพงกว่าvectorการดำเนินการที่เทียบเท่ากัน (เล็กน้อย) ในทางกลับกันการใช้อินสแตนซ์จำนวนมาก / จำนวนมากvectorอาจทำให้เกิดการกระจายตัวของฮีปโดยไม่จำเป็น (ทำให้การโทรช้าลงnew)
นอกจากนี้ยังเป็นแหลมออกอื่น ๆ ใน StackOverflowมีการสนทนาที่ดีอื่น ๆ อีกมากมายที่นี่: http://www.gotw.ca/gotw/054.htm
หากต้องการทราบความแตกต่างเราควรทราบวิธีdequeการนำไปใช้โดยทั่วไป หน่วยความจำถูกจัดสรรเป็นบล็อกที่มีขนาดเท่ากันและจะถูกรวมเข้าด้วยกัน (เป็นอาร์เรย์หรืออาจเป็นเวกเตอร์)
ดังนั้นหากต้องการค้นหาองค์ประกอบที่ n คุณจะพบบล็อกที่เหมาะสมจากนั้นเข้าถึงองค์ประกอบที่อยู่ภายในนั้น นี่เป็นเวลาคงที่เพราะมันมักจะค้นหา 2 ครั้ง แต่นั่นก็ยังมากกว่าเวกเตอร์
vectorยังทำงานได้ดีกับ API ที่ต้องการบัฟเฟอร์ที่ต่อเนื่องกันเนื่องจากเป็น C API หรือมีความหลากหลายมากกว่าในการใช้ตัวชี้และความยาว (ดังนั้นคุณสามารถมีเวกเตอร์อยู่ข้างใต้หรืออาร์เรย์ปกติและเรียก API จากบล็อกหน่วยความจำของคุณ)
ในกรณีที่dequeมีข้อได้เปรียบที่ใหญ่ที่สุดคือ:
อย่างที่สองเป็นที่รู้จักน้อยกว่า แต่สำหรับคอลเลกชันขนาดใหญ่มาก:
เมื่อฉันจัดการกับคอลเลกชันขนาดใหญ่ในอดีตและย้ายจากโมเดลที่ต่อเนื่องกันไปเป็นโมเดลบล็อกเราสามารถจัดเก็บคอลเลคชันขนาดใหญ่ได้ประมาณ 5 เท่าก่อนที่หน่วยความจำจะหมดในระบบ 32 บิต ส่วนหนึ่งเป็นเพราะเมื่อทำการจัดสรรใหม่จำเป็นต้องจัดเก็บบล็อกเก่าและบล็อกใหม่ก่อนที่จะคัดลอกองค์ประกอบ
เมื่อพูดทั้งหมดนี้คุณอาจมีปัญหากับstd::dequeระบบที่ใช้การจัดสรรหน่วยความจำแบบ "มองโลกในแง่ดี" ในขณะที่ความพยายามที่จะขอขนาดบัฟเฟอร์ขนาดใหญ่สำหรับการจัดสรรใหม่ของ a vectorอาจจะถูกปฏิเสธในบางจุดด้วย a bad_allocลักษณะที่มองโลกในแง่ดีของผู้จัดสรรมักจะให้การร้องขอสำหรับบัฟเฟอร์ขนาดเล็กที่ร้องขอโดย a dequeและมีแนวโน้มที่จะก่อให้เกิด ระบบปฏิบัติการจะฆ่ากระบวนการเพื่อพยายามรับหน่วยความจำบางส่วน เลือกอันไหนก็อาจจะไม่ถูกใจนัก
วิธีแก้ปัญหาในกรณีดังกล่าว ได้แก่ การตั้งค่าแฟล็กระดับระบบเพื่อลบล้างการจัดสรรในแง่ดี (ไม่สามารถทำได้เสมอไป) หรือจัดการหน่วยความจำด้วยตนเองค่อนข้างมากขึ้นเช่นการใช้ตัวจัดสรรของคุณเองที่ตรวจสอบการใช้หน่วยความจำหรือสิ่งที่คล้ายกัน เห็นได้ชัดว่าไม่เหมาะอย่างยิ่ง (ซึ่งอาจตอบคำถามของคุณได้ว่าชอบเวกเตอร์ ... )
ฉันใช้ทั้ง vector และ deque หลายครั้งแล้ว deque มีความซับซ้อนมากขึ้นอย่างมากจากมุมมองของการนำไปใช้งาน ความซับซ้อนนี้แปลเป็นรหัสมากขึ้นและรหัสที่ซับซ้อนมากขึ้น ดังนั้นโดยทั่วไปคุณจะเห็นขนาดโค้ดเมื่อคุณเลือก deque ทับเวกเตอร์ นอกจากนี้คุณยังอาจได้รับการตีด้วยความเร็วเพียงเล็กน้อยหากโค้ดของคุณใช้เฉพาะสิ่งที่เวกเตอร์เก่งเท่านั้น
หากคุณต้องการคิวสองครั้ง deque คือผู้ชนะที่ชัดเจน แต่ถ้าคุณใช้ส่วนแทรกส่วนใหญ่แล้วลบที่ด้านหลังเวกเตอร์จะเป็นผู้ชนะที่ชัดเจน เมื่อคุณไม่แน่ใจให้ประกาศคอนเทนเนอร์ของคุณด้วย typedef (เพื่อให้ง่ายต่อการสลับไปมา) และวัดผล
vector.) ฉันได้เขียนการดำเนินการเชื่อมโยงไปยังด้านล่างในคำตอบของฉัน สามารถทำได้เร็วพอ ๆ กับ a vectorแต่ใช้ได้อย่างกว้างขวางกว่ามาก (เช่นเมื่อทำการต่อคิวอย่างรวดเร็ว)
std::dequeไม่ได้รับประกันหน่วยความจำต่อเนื่อง - และมักจะค่อนข้างช้ากว่าสำหรับการเข้าถึงแบบดัชนี โดยทั่วไปจะใช้ deque เป็น "รายการเวกเตอร์"
อ้างอิงจากhttp://www.cplusplus.com/reference/stl/deque/ "ซึ่งแตกต่างจากเวกเตอร์คือไม่รับประกันว่า deques จะมีองค์ประกอบทั้งหมดในสถานที่จัดเก็บที่ต่อเนื่องกันทำให้ไม่สามารถเข้าถึงได้อย่างปลอดภัยโดยใช้เลขคณิตตัวชี้"
Deques ซับซ้อนกว่าเล็กน้อยส่วนหนึ่งเป็นเพราะพวกเขาไม่จำเป็นต้องมีเค้าโครงหน่วยความจำที่ต่อเนื่องกัน หากคุณต้องการคุณสมบัตินั้นคุณไม่ควรใช้ deque
(ก่อนหน้านี้คำตอบของฉันแสดงให้เห็นถึงการขาดมาตรฐาน (จากแหล่งข้อมูลเดียวกันกับข้างต้น "deques อาจถูกนำไปใช้โดยไลบรารีเฉพาะในรูปแบบที่แตกต่างกัน") แต่จริงๆแล้วใช้กับประเภทข้อมูลไลบรารีมาตรฐานเท่านั้น)
std::dequestd::vectorไม่น้อยกว่ามาตรฐาน ฉันไม่เชื่อว่าข้อกำหนดด้านความซับซ้อนstd::dequeจะเป็นไปตามที่จัดเก็บข้อมูลที่ต่อเนื่องกันได้
dequeไม่สามารถรองรับกับพื้นที่เก็บข้อมูลที่ต่อเนื่องกันได้?
dequeกล่าวคือการแทรกที่ปลายจะไม่ทำให้การอ้างอิงถึงองค์ประกอบที่มีอยู่เป็นโมฆะ ข้อกำหนดนี้แสดงถึงหน่วยความจำที่ไม่ต่อเนื่อง
deque เป็นคอนเทนเนอร์ลำดับที่อนุญาตให้เข้าถึงองค์ประกอบโดยสุ่ม แต่ไม่รับประกันว่าจะมีพื้นที่จัดเก็บที่ต่อเนื่อง
ฉันคิดว่าเป็นความคิดที่ดีที่จะทำการทดสอบประสิทธิภาพของแต่ละกรณี และตัดสินใจโดยอาศัยการทดสอบนี้
ฉันชอบstd::dequeมากกว่าstd::vectorในกรณีส่วนใหญ่
vectorคนต้องการ เราสามารถสรุปได้ว่าเหตุใดจึงไม่เป็นข้อพิสูจน์ การบอกว่าคุณชอบdequeโดยไม่ทราบสาเหตุจากการทดสอบที่ไม่ระบุรายละเอียดไม่ใช่คำตอบ
คุณไม่ต้องการให้เวกเตอร์ลบล้างตามผลการทดสอบเหล่านี้ (พร้อมแหล่งที่มา)
แน่นอนคุณควรทดสอบในแอป / สภาพแวดล้อมของคุณ แต่โดยสรุป:
ข้อมูลเพิ่มเติมบางส่วนและหมายเหตุที่ควรพิจารณา Circular_buffer
ในแง่หนึ่งเวกเตอร์มักจะค่อนข้างเร็วกว่า deque หากคุณไม่ต้องการคุณสมบัติทั้งหมดของ deque ให้ใช้เวกเตอร์
ในทางกลับกันบางครั้งคุณทำคุณลักษณะจำเป็นซึ่งเวกเตอร์ไม่ได้ให้คุณในกรณีที่คุณต้องใช้ deque ตัวอย่างเช่นฉันขอท้าให้ทุกคนพยายามเขียนโค้ดนี้ใหม่โดยไม่ต้องใช้ deque และไม่ต้องแก้ไขอัลกอริทึมมหาศาล
push_backและpop_backการดำเนินการเดียวกันdeque<int>นั้นเร็วกว่าvector<int>การทดสอบของฉันอย่างน้อย 20% เสมอ(gcc กับ O3) ฉันเดาว่านั่นคือเหตุผลที่dequeเป็นตัวเลือกมาตรฐานสำหรับสิ่งต่างๆเช่นstd::stack...
โปรดทราบว่าหน่วยความจำเวกเตอร์จะถูกจัดสรรใหม่เมื่ออาร์เรย์เติบโตขึ้น หากคุณมีตัวชี้ไปยังองค์ประกอบเวกเตอร์องค์ประกอบเหล่านั้นจะไม่ถูกต้อง
นอกจากนี้หากคุณลบองค์ประกอบตัวทำซ้ำจะไม่ถูกต้อง (แต่ไม่ใช่ "สำหรับ (อัตโนมัติ ... )")
แก้ไข: เปลี่ยน 'deque' เป็น 'vector'
std::dequeมีขนาดบล็อกสูงสุดที่เล็กมาก (~ 16 ไบต์ถ้าฉันจำได้ถูกต้องอาจเป็น 32) และด้วยเหตุนี้จึงทำงานได้ไม่ดีนักสำหรับแอปพลิเคชันที่สมจริง โดยdeque<T>ที่sizeof(T) > 8(หรือ 16 เป็นตัวเลขเล็ก ๆ ) มีลักษณะการทำงานเหมือนกับ avector<T*>โดยที่แต่ละองค์ประกอบได้รับการจัดสรรแบบไดนามิก การใช้งานอื่น ๆdequeที่มีขนาดของบล็อกสูงสุดแตกต่างกันดังนั้นการเขียนโค้ดที่มีค่อนข้างลักษณะการทำงานเดียวกันบนแพลตฟอร์มที่แตกต่างเป็นเรื่องยากกับ