แม้ว่า @Marc จะให้การวิเคราะห์ที่ยอดเยี่ยม (สิ่งที่ฉันคิดว่า) เป็นบางคนอาจต้องการพิจารณาสิ่งต่าง ๆ จากมุมที่แตกต่างกันเล็กน้อย
วิธีหนึ่งคือการพิจารณาวิธีการจัดสรรที่แตกต่างกันเล็กน้อย แทนที่จะคัดลอกองค์ประกอบทั้งหมดจากที่เก็บข้อมูลเก่าไปยังที่จัดเก็บใหม่ทันทีพิจารณาคัดลอกเพียงหนึ่งองค์ประกอบต่อครั้ง - เช่นแต่ละครั้งที่คุณทำ push_back จะเพิ่มองค์ประกอบใหม่ไปยังพื้นที่ใหม่และคัดลอกหนึ่งที่มีอยู่ องค์ประกอบจากพื้นที่เก่าไปยังพื้นที่ใหม่ สมมติว่าปัจจัยการเจริญเติบโตของ 2 มันค่อนข้างชัดเจนว่าเมื่อพื้นที่ใหม่เต็มเราจะทำการคัดลอกองค์ประกอบทั้งหมดจากพื้นที่เก่าไปยังพื้นที่ใหม่เสร็จแล้วและ push_back แต่ละแห่งก็มีเวลาคงที่ ณ จุดนี้เราจะทิ้งพื้นที่เก่าจัดสรรบล็อกหน่วยความจำใหม่ที่เพิ่มขึ้นเป็นสองเท่าและทำซ้ำกระบวนการ
เห็นได้ชัดว่าเราสามารถดำเนินการต่อไปเรื่อย ๆ (หรือตราบใดที่มีหน่วยความจำอยู่แล้ว) และทุก ๆ push_back จะเกี่ยวข้องกับการเพิ่มองค์ประกอบใหม่และคัดลอกองค์ประกอบเก่าหนึ่งองค์ประกอบ
การนำไปใช้โดยทั่วไปยังคงมีจำนวนสำเนาเท่ากัน - แต่แทนที่จะทำสำเนาทีละรายการจะทำการคัดลอกองค์ประกอบที่มีอยู่ทั้งหมดในคราวเดียว ในอีกด้านหนึ่งคุณพูดถูก: หมายความว่าถ้าคุณดูข้อความเชิญของ push_back แต่ละรายการบางข้อความจะช้ากว่าคนอื่นมาก หากเราดูค่าเฉลี่ยระยะยาวจำนวนการคัดลอกที่ทำต่อการเรียกใช้ของ push_back จะคงที่ไม่ว่าขนาดของเวกเตอร์จะเป็นเท่าใด
แม้ว่ามันจะไม่เกี่ยวข้องกับความซับซ้อนในการคำนวณ แต่ฉันคิดว่ามันคุ้มค่าที่จะชี้ให้เห็นว่าทำไมการทำสิ่งต่าง ๆ ในขณะที่ทำนั้นมีประโยชน์มากกว่าการคัดลอกองค์ประกอบหนึ่งรายการต่อ push_back ดังนั้นเวลาต่อ push_back จึงคงที่ มีเหตุผลอย่างน้อยสามประการที่ต้องพิจารณา
แรกคือความพร้อมหน่วยความจำเพียง หน่วยความจำเก่าสามารถทำให้เป็นอิสระสำหรับการใช้งานอื่น ๆ ได้เฉพาะหลังจากการคัดลอกเสร็จสิ้น หากคุณคัดลอกทีละหนึ่งไอเท็มบล็อกหน่วยความจำเก่าจะยังคงถูกจัดสรรอีกต่อไป ในความเป็นจริงคุณจะมีบล็อกเก่าหนึ่งบล็อกและบล็อกใหม่หนึ่งบล็อกที่จัดสรรเป็นหลักตลอดเวลา หากคุณตัดสินใจเลือกปัจจัยการเจริญเติบโตที่เล็กกว่าสอง (ซึ่งปกติคุณต้องการ) คุณจะต้องจัดสรรหน่วยความจำให้มากขึ้นตลอดเวลา
ประการที่สองถ้าคุณคัดลอกองค์ประกอบเก่าเพียงครั้งเดียวการทำดัชนีในอาร์เรย์จะยุ่งยากกว่าเล็กน้อย - การดำเนินการทำดัชนีแต่ละครั้งจะต้องคิดออกว่าองค์ประกอบที่ดัชนีที่กำหนดนั้นอยู่ในบล็อกหน่วยความจำเก่าหรือ อันใหม่. นั่นไม่ได้ซับซ้อนอะไรมากนัก แต่สำหรับการดำเนินการเบื้องต้นเช่นการจัดทำดัชนีในอาเรย์การชะลอตัวอาจมีความสำคัญมาก
ประการที่สามโดยการคัดลอกทั้งหมดในครั้งเดียวคุณจะได้รับประโยชน์มากขึ้นจากการแคช การคัดลอกทั้งหมดในครั้งเดียวคุณสามารถคาดหวังได้ว่าทั้งต้นทางและปลายทางจะอยู่ในแคชในกรณีส่วนใหญ่ดังนั้นค่าใช้จ่ายของแคชมิสจะถูกตัดจำหน่ายตามจำนวนองค์ประกอบที่จะพอดีกับบรรทัดแคช หากคุณคัดลอกองค์ประกอบหนึ่งครั้งคุณอาจพลาดแคชได้อย่างง่ายดายสำหรับทุกองค์ประกอบที่คุณคัดลอก นั่นเปลี่ยนเพียงปัจจัยคงที่ไม่ใช่ความซับซ้อน แต่ยังคงมีความสำคัญพอสมควร - สำหรับเครื่องทั่วไปคุณสามารถคาดหวังได้ง่ายถึงปัจจัย 10 ถึง 20
มันอาจคุ้มค่าที่จะพิจารณาทิศทางอื่นสักครู่: ถ้าคุณกำลังออกแบบระบบที่มีข้อกำหนดแบบเรียลไทม์มันอาจจะเหมาะสมที่จะคัดลอกเพียงองค์ประกอบเดียวในแต่ละครั้งแทนที่จะเป็นทั้งหมดในคราวเดียว แม้ว่าความเร็วโดยรวมอาจจะ (หรืออาจจะไม่ต่ำกว่า) แต่คุณก็ยังคงมีขอบเขตบนที่ยากสำหรับการเรียกใช้ push_back เพียงครั้งเดียว - โดยสันนิษฐานว่าคุณมีตัวจัดสรรแบบเรียลไทม์ ระบบนั้นห้ามการจัดสรรหน่วยความจำแบบไดนามิกเลยอย่างน้อยก็ในส่วนที่มีข้อกำหนดแบบเรียลไทม์)