Outros já trataram dos outros problemas, então vou apenas observar um ponto: você já quis excluir manualmente um objeto.
A resposta é sim. @DavidSchwartz deu um exemplo, mas é bastante incomum. Vou dar um exemplo que está por trás do que muitos programadores de C ++ usam o tempo todo: std::vector(e std::deque, embora não seja usado tanto).
Como a maioria das pessoas sabe, std::vectoralocará um bloco maior de memória quando / se você adicionar mais itens do que sua alocação atual pode conter. Quando ele faz isso, no entanto, ele tem um bloco de memória que é capaz de conter mais objetos do que atualmente no vetor.
Para gerenciar isso, o vectorque nos oculta é alocar memória bruta por meio do Allocatorobjeto (o que, a menos que você especifique de outra forma, significa que ele usa ::operator new). Então, quando você usa (por exemplo) push_backpara adicionar um item ao vector, internamente o vetor usa a placement newpara criar um item na parte (anteriormente) não utilizada de seu espaço de memória.
Agora, o que acontece quando / se você eraseum item do vetor? Ele não pode simplesmente usar delete- isso liberaria todo o seu bloco de memória; ele precisa destruir um objeto naquela memória sem destruir nenhum outro, ou liberar qualquer bloco de memória que ele controla (por exemplo, se você erase5 itens de um vetor, então imediatamente push_back5 mais itens, é garantido que o vetor não será realocado memória quando você faz isso.
Para fazer isso, o vetor destrói diretamente os objetos na memória chamando explicitamente o destruidor, não usando delete.
Se, por acaso, outra pessoa fosse escrever um contêiner usando armazenamento contíguo mais ou menos como um vectorfaz (ou alguma variante disso, como std::dequerealmente faz), você quase certamente desejaria usar a mesma técnica.
Apenas por exemplo, vamos considerar como você pode escrever código para um buffer circular.
#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
Ao contrário dos contêineres padrão, este usa operator newe operator deletediretamente. Para uso real, você provavelmente deseja usar uma classe alocadora, mas no momento faria mais para distrair do que contribuir (IMO, de qualquer maneira).