Orang lain telah membahas masalah lain, jadi saya hanya akan melihat satu hal: apakah Anda pernah ingin menghapus objek secara manual.
Jawabannya iya. @DavidSchwartz memberi satu contoh, tapi itu cukup satu tidak biasa. Saya akan memberikan contoh yang ada di balik terpal dari apa yang banyak digunakan programmer C ++ sepanjang waktu: std::vector
(dan std::deque
, meskipun tidak terlalu banyak digunakan).
Seperti yang diketahui kebanyakan orang, std::vector
akan mengalokasikan blok memori yang lebih besar ketika / jika Anda menambahkan lebih banyak item daripada yang dapat ditampung oleh alokasi saat ini. Namun, ketika melakukan ini, ia memiliki blok memori yang mampu menampung lebih banyak objek daripada yang ada di vektor.
Untuk mengelolanya, apa yang vector
dilakukan di bawah selimut adalah mengalokasikan memori mentah melalui Allocator
objek (yang, kecuali Anda menentukan sebaliknya, berarti digunakannya ::operator new
). Kemudian, saat Anda menggunakan (misalnya) push_back
untuk menambahkan item ke vector
, secara internal vektor menggunakan a placement new
untuk membuat item di bagian ruang memorinya (yang sebelumnya) tidak terpakai.
Sekarang, apa yang terjadi jika / jika Anda erase
merupakan item dari vektor? Itu tidak bisa begitu saja delete
- itu akan melepaskan seluruh blok memorinya; ia perlu menghancurkan satu objek dalam memori itu tanpa merusak yang lain, atau melepaskan salah satu blok memori yang dikendalikannya (misalnya, jika Anda erase
5 item dari vektor, lalu segera push_back
5 item lagi, dijamin bahwa vektor tidak akan dialokasikan kembali memori saat Anda melakukannya.
Untuk melakukan itu, vektor secara langsung menghancurkan objek dalam memori dengan secara eksplisit memanggil destruktor, bukan dengan menggunakan delete
.
Jika, mungkin, ada orang lain yang menulis wadah menggunakan penyimpanan yang berdekatan secara kasar seperti yang vector
dilakukan (atau beberapa varian dari itu, seperti yang std::deque
sebenarnya), Anda hampir pasti ingin menggunakan teknik yang sama.
Sebagai contoh, mari pertimbangkan bagaimana Anda dapat menulis kode untuk buffer cincin melingkar.
#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
Berbeda dengan wadah standar, ini menggunakan operator new
dan operator delete
langsung. Untuk penggunaan nyata, Anda mungkin ingin menggunakan kelas pengalokasi, tetapi untuk saat ini akan melakukan lebih banyak hal untuk mengalihkan perhatian daripada berkontribusi (bagaimanapun juga, IMO).