จริง ๆ แล้วเป็นชนิดที่จำเป็นในการใช้โครงสร้างข้อมูลชนิดใด ๆ ที่จัดสรรหน่วยความจำได้มากกว่าที่จำเป็นเล็กน้อยสำหรับจำนวนองค์ประกอบที่ใส่เข้าไป (เช่นสิ่งอื่นใดนอกจากโครงสร้างที่เชื่อมโยงซึ่งจัดสรรหนึ่งโหนดต่อครั้ง)
ภาชนะที่ใช้เวลาชอบunordered_map
, หรือvector
deque
สิ่งเหล่านี้ทั้งหมดจัดสรรหน่วยความจำมากกว่าที่จำเป็นสำหรับองค์ประกอบที่คุณใส่น้อยที่สุดเพื่อหลีกเลี่ยงการจัดสรรฮีปสำหรับการแทรกทุกครั้ง ลองใช้vector
เป็นตัวอย่างที่ง่ายที่สุด
เมื่อคุณทำ:
vector<Foo> vec;
// Allocate memory for a thousand Foos:
vec.reserve(1000);
... ที่ไม่ได้สร้างพัน Foos จริงๆ มันเพียงจัดสรร / จองหน่วยความจำสำหรับพวกเขา หากvector
ไม่ได้ใช้ตำแหน่งใหม่ที่นี่จะเป็นการสร้างค่าเริ่มต้นFoos
ไปทั่วสถานที่รวมถึงการเรียกใช้ destructors ของพวกเขาแม้สำหรับองค์ประกอบที่คุณไม่เคยใส่แม้แต่ในสถานที่แรก
การจัดสรร! = การก่อสร้างการปลดปล่อย! = การทำลาย
เพียงแค่พูดโดยทั่วไปเพื่อใช้โครงสร้างข้อมูลจำนวนมากเช่นด้านบนคุณไม่สามารถทำการจัดสรรหน่วยความจำและสร้างองค์ประกอบเป็นสิ่งที่แบ่งแยกไม่ได้และคุณก็ไม่สามารถรักษาหน่วยความจำที่ว่างเปล่าและทำลายองค์ประกอบได้เช่นกัน
จะต้องมีการแยกระหว่างความคิดเหล่านี้เพื่อหลีกเลี่ยงการอ้างถึง constructors และ destructors ที่ไม่จำเป็นซ้ายและขวาโดยไม่จำเป็นและนั่นเป็นสาเหตุที่ไลบรารี่มาตรฐานแยกความคิดของstd::allocator
(ซึ่งไม่ได้สร้างหรือทำลายองค์ประกอบเมื่อจัดสรร / ปลดปล่อยหน่วยความจำ *) ภาชนะบรรจุที่ใช้มันซึ่งสร้างองค์ประกอบด้วยตนเองโดยใช้การจัดวางองค์ประกอบใหม่และทำลายองค์ประกอบด้วยตนเองโดยใช้การเรียกใช้อย่างชัดเจนของ destructors
- ฉันเกลียดการออกแบบ
std::allocator
แต่นั่นเป็นอีกเรื่องที่ฉันจะหลีกเลี่ยงการพูดจาโผงผาง :-D
ดังนั้นฉันมักจะใช้มันมากตั้งแต่ฉันเขียนคอนเทนเนอร์ C ++ ที่เป็นไปตามมาตรฐานทั่วไปที่ไม่สามารถสร้างในแง่ของคอนเทนเนอร์ที่มีอยู่ทั่วไปได้ สิ่งที่รวมอยู่ในนั้นคือการนำเวกเตอร์ขนาดเล็กมาใช้ฉันได้สร้างสองสามทศวรรษที่ผ่านมาเพื่อหลีกเลี่ยงการจัดสรรฮีปในกรณีทั่วไปและ trie ที่มีประสิทธิภาพหน่วยความจำ (ไม่จัดสรรทีละโหนด) ในทั้งสองกรณีฉันไม่สามารถนำไปใช้งานจริงได้โดยใช้คอนเทนเนอร์ที่มีอยู่ดังนั้นฉันจึงต้องใช้placement new
เพื่อหลีกเลี่ยงการกล่าวอ้างสิ่งก่อสร้างและสิ่งทำลายล้างในสิ่งที่ไม่จำเป็นทั้งซ้ายและขวา
โดยปกติถ้าคุณทำงานร่วมกับตัวจัดสรรแบบกำหนดเองเพื่อจัดสรรวัตถุเป็นรายบุคคลเช่นรายการฟรีคุณก็มักต้องการใช้placement new
เช่นนี้ (ตัวอย่างพื้นฐานที่ไม่รบกวนความปลอดภัยหรือ RAII):
Foo* foo = new(free_list.allocate()) Foo(...);
...
foo->~Foo();
free_list.free(foo);