คนอื่น ๆ ได้แก้ไขปัญหาอื่น ๆ แล้วดังนั้นฉันจะดูที่จุดเดียว: คุณเคยต้องการลบวัตถุด้วยตนเองหรือไม่
คำตอบคือใช่ @DavidSchwartz ยกตัวอย่างหนึ่ง แต่มันเป็นเรื่องที่ค่อนข้างผิดปกติ ฉันจะยกตัวอย่างที่อยู่ภายใต้ประทุนของสิ่งที่โปรแกรมเมอร์ C ++ จำนวนมากใช้ตลอดเวลา: std::vector
(และstd::deque
แม้ว่าจะไม่ได้ใช้มากนัก)
ตามที่คนส่วนใหญ่ทราบstd::vector
จะจัดสรรหน่วยความจำขนาดใหญ่ขึ้นเมื่อ / หากคุณเพิ่มรายการมากเกินกว่าที่การจัดสรรในปัจจุบันจะสามารถรองรับได้ เมื่อมันไม่นี้ แต่ก็มีบล็อกของหน่วยความจำที่มีความสามารถในการถือครองเพิ่มเติมวัตถุกว่าอยู่ในขณะนี้เวกเตอร์
ในการจัดการสิ่งvector
นั้นสิ่งที่ทำภายใต้การครอบคลุมคือการจัดสรรหน่วยความจำดิบผ่านAllocator
อ็อบเจ็กต์ (ซึ่งเว้นแต่คุณจะระบุเป็นอย่างอื่นหมายความว่าใช้::operator new
) จากนั้นเมื่อคุณใช้ (ตัวอย่าง) push_back
เพื่อเพิ่มไอเท็มลงในvector
เวกเตอร์ภายในจะใช้ a placement new
เพื่อสร้างไอเท็มในส่วนที่ไม่ได้ใช้ (ก่อนหน้านี้) ของพื้นที่หน่วยความจำ
ทีนี้จะเกิดอะไรขึ้นเมื่อ / ถ้าคุณerase
เป็นรายการจากเวกเตอร์ มันไม่สามารถใช้ได้delete
- นั่นจะปล่อยบล็อกหน่วยความจำทั้งหมด จำเป็นต้องทำลายวัตถุหนึ่งชิ้นในหน่วยความจำนั้นโดยไม่ทำลายสิ่งอื่นใดหรือปล่อยบล็อกหน่วยความจำใด ๆ ที่ควบคุม (ตัวอย่างเช่นถ้าคุณerase
5 รายการจากเวกเตอร์จากนั้นpush_back
อีก 5 รายการทันทีรับประกันว่าเวกเตอร์จะไม่จัดสรรใหม่ ความทรงจำเมื่อคุณทำเช่นนั้น
ต้องการทำเช่นนั้นเวกเตอร์โดยตรงทำลายวัตถุในหน่วยความจำโดยชัดเจนโทร destructor ที่ไม่ได้delete
โดยใช้
ถ้าเป็นไปได้มีคนอื่นเขียนคอนเทนเนอร์โดยใช้การจัดเก็บที่ต่อเนื่องกันโดยประมาณเช่น a vector
(หรือตัวแปรบางอย่างเช่นstd::deque
นั้นจริงๆ) คุณเกือบจะต้องการใช้เทคนิคเดียวกัน
ตัวอย่างเช่นลองพิจารณาว่าคุณจะเขียนโค้ดสำหรับบัฟเฟอร์วงแหวนแบบวงกลมได้อย่างไร
#ifndef CBUFFER_H_INC
#define CBUFFER_H_INC
template <class T>
class circular_buffer {
T *data;
unsigned read_pos;
unsigned write_pos;
unsigned in_use;
const unsigned capacity;
public:
circular_buffer(unsigned size) :
data((T *)operator new(size * sizeof(T))),
read_pos(0),
write_pos(0),
in_use(0),
capacity(size)
{}
void push(T const &t) {
// ensure there's room in buffer:
if (in_use == capacity)
pop();
// construct copy of object in-place into buffer
new(&data[write_pos++]) T(t);
// keep pointer in bounds.
write_pos %= capacity;
++in_use;
}
// return oldest object in queue:
T front() {
return data[read_pos];
}
// remove oldest object from queue:
void pop() {
// destroy the object:
data[read_pos++].~T();
// keep pointer in bounds.
read_pos %= capacity;
--in_use;
}
~circular_buffer() {
// first destroy any content
while (in_use != 0)
pop();
// then release the buffer.
operator delete(data);
}
};
#endif
ซึ่งแตกต่างจากภาชนะมาตรฐานนี้ใช้operator new
และoperator delete
โดยตรง สำหรับการใช้งานจริงคุณอาจต้องการใช้คลาสตัวจัดสรร แต่ในขณะนี้การเบี่ยงเบนความสนใจมากกว่าการมีส่วนร่วม (IMO)