D'autres ont déjà abordé les autres questions, je vais donc il suffit de regarder un point: ne jamais vous voulez supprimer manuellement un objet.
La réponse est oui. @DavidSchwartz a donné un exemple, mais c'est assez inhabituel. Je vais vous donner un exemple qui est sous le capot de ce que beaucoup de programmeurs C++ utilise tout le temps: std::vector
(et std::deque
, si elle n'est pas utilisée tout autant).
Comme la plupart des gens savent, std::vector
va allouer un plus grand bloc de mémoire quand/si vous ajoutez plus d'éléments que de sa répartition actuelle. Quand il le fait, cependant, il a un bloc de mémoire qui est capable de tenir plus d' objets que ceux qui sont actuellement dans le vecteur.
À gérer que ce qu' vector
n'sous les couvertures est d'allouer brut de la mémoire via l' Allocator
objet (qui, sauf indication contraire, les moyens qu'elle utilise ::operator new
). Puis, lorsque vous utilisez (par exemple) push_back
pour ajouter un élément à l' vector
, en interne, le vecteur utilise un placement new
de créer un élément dans la (déjà) la partie inutilisée de son espace mémoire.
Maintenant, ce qui arrive quand/si vous erase
d'un élément dans le vecteur? Il ne peut pas utiliser delete
-- qui aurait communiqué son bloc entier de la mémoire; il a besoin de détruire un objet en mémoire, sans détruire les autres, ou la libération de tout le bloc de mémoire qu'elle contrôle (par exemple, si vous erase
5 articles à partir d'un vecteur, puis immédiatement push_back
5 plus d'articles, il est garanti que le vecteur sera pas réallouer la mémoire lorsque vous le faites.
Pour ce faire, le vecteur directement détruit les objets dans la mémoire en appelant explicitement le destructeur, pas en utilisant delete
.
Si, d'aventure, quelqu'un d'autre l'ont été pour écrire un conteneur à l'aide de stockage contigu à peu près comme un vector
(ou une variante de cela, comme std::deque
vraiment), vous pourriez presque certainement envie d'utiliser la même technique.
Juste pour exemple, considérons la façon dont vous pouvez écrire du code pour un anneau circulaire-tampon.
#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;
}
// release the buffer:
~circular_buffer() { operator delete(data); }
};
#endif
Contrairement aux conteneurs standard, il utilise operator new
et operator delete
directement. De l'utilisation réelle, vous probablement ne voulez utiliser un allocateur de classe, mais pour le moment, ce serait faire plus pour distraire que de contribuer (OMI, de toute façon).