Diğerleri zaten diğer sorunları ele aldı, bu yüzden sadece bir noktaya bakacağım: bir nesneyi manuel olarak silmek istiyor musunuz?
Cevap Evet. @DavidSchwartz bir örnek verdi, ancak oldukça sıra dışı bir örnek. Pek çok C ++ programcısının her zaman kullandığı şeyin altını çizen bir örnek vereceğim: std::vector
(vestd::deque
Pek çok pek kullanılmasa da).
Çoğu kişinin bildiği gibi, std::vector
mevcut tahsisinin tutabileceğinden daha fazla öğe eklerseniz / eklediğinizde daha büyük bir bellek bloğu ayıracaktır. Ancak bunu yaptığında, şu anda vektörde olandan daha fazla nesneyi tutabilen bir bellek bloğuna sahiptir .
Bunu yönetmek için, vector
kapakların altında yapılan şey , nesne aracılığıyla ham bellek tahsis etmektir Allocator
(aksi belirtilmedikçe, kullandığı anlamına gelir ::operator new
). Ardından, push_back
öğesine bir öğe eklemek için (örneğin) vector
kullandığınızda, dahili olarak vektör placement new
, bellek alanının (daha önce) kullanılmamış kısmında bir öğe oluşturmak için a kullanır .
Şimdi, erase
vektörden bir öğe olursanız / olursanız ne olur ? Sadece kullanamaz delete
- bu tüm bellek bloğunu serbest bırakır; diğerlerini yok etmeden veya kontrol ettiği bellek bloklarından herhangi birini serbest bırakmadan o bellekteki bir nesneyi yok etmesi gerekir (örneğin, erase
bir vektörden 5 öğe, ardından hemen push_back
5 öğe daha alırsanız , vektörün yeniden tahsis edilmeyeceği garanti edilir. bunu yaptığınızda hafıza.
Bunu yapmak için vektör, kullanarak değil , açıkça yıkıcıyı çağırarak bellekteki nesneleri doğrudan yok eder delete
.
Muhtemelen, bir başkası kabaca bir vector
yaptığı gibi bitişik depolamayı kullanarak bir kap yazacak olsaydı (veya std::deque
gerçekten yaptığı gibi bunun bir çeşidini ), neredeyse kesinlikle aynı tekniği kullanmak istersiniz.
Örneğin, dairesel bir halka tampon için nasıl kod yazabileceğinizi düşünelim.
#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
Standart konteynerlerin aksine, bu operator new
ve operator delete
doğrudan kullanır . Gerçek kullanım için, muhtemelen bir ayırıcı sınıf kullanmak istersiniz, ancak şu an için dikkatinizi dağıtmak için katkıda bulunmaktan daha fazlasını yapacaktır (IMO, neyse).