A quelqu'un ici jamais utilisé le C++de "placement de nouvelles"? Si oui, pour quoi faire? Il me semble qu'il serait utile sur le matériel mappé en mémoire.
Réponses
Trop de publicités?Le Placement de nouvelles permet de construire un objet sur la mémoire déjà allouée.
Vous pouvez le faire pour des optimisations (il est plus rapide de ne pas attribuer de nouveau tout le temps), mais vous avez besoin de re-construire un objet à plusieurs reprises. Si vous avez besoin de garder ré-affectation, il peut être plus efficace d'allouer plus que vous avez besoin, même si vous ne voulez pas utiliser pour l'instant.
Devex donne un bon exemple:
Standard C++ prend également en charge le placement nouvel opérateur, qui construit une sur l'objet d'un pré-mémoire tampon allouée. Cette est utile lors de la création d'un pool de mémoire, un garbage collector ou tout simplement lorsque de la performance et de l'exception de sécurité sont primordiale (il n'y a pas de danger de l'allocation à l'échec, puisque la mémoire a déjà été attribué, et construction d'un objet sur un pré-alloué de la mémoire tampon prend moins de temps):
char *buf = new char[sizeof(string)]; // pre-allocated buffer
string *p = new (buf) string("hi"); // placement new
string *q = new string("hi"); // ordinary heap allocation
Vous pouvez également être sûr qu'il y a peut être pas d'échec d'allocation à une certaine partie de la critique de code (peut-être que vous travaillez sur un stimulateur cardiaque, par exemple). Dans ce cas, vous pouvez utiliser le placement de nouvelles.
Libération de la mémoire dans le placement de nouvelles
Vous ne devriez pas libérer tous les objets à l'aide de la mémoire tampon. Au lieu de cela, vous devez le supprimer[] seul le tampon d'origine. Vous devez ensuite appeler les destructeurs directement de vos classes manuellement. Pour une bonne suggestion sur cette s'il vous plaît voir de Stroustrup FAQ: Est-il un "placement supprimer"?
Nous l'utilisons à la coutume des pools de mémoire. Juste un croquis:
class Pool {
public:
Pool() { /* implementation details irrelevant */ };
virtual ~Pool() { /* ditto */ };
virtual void *allocate(size_t);
virtual void deallocate(void *);
static Pool::misc_pool() { return misc_pool_p; /* global MiscPool for general use */ }
};
class ClusterPool : public Pool { /* ... */ };
class FastPool : public Pool { /* ... */ };
class MapPool : public Pool { /* ... */ };
class MiscPool : public Pool { /* ... */ };
// elsewhere...
void *pnew_new(size_t size)
{
return Pool::misc_pool()->allocate(size);
}
void *pnew_new(size_t size, Pool *pool_p)
{
if (!pool_p) {
return Pool::misc_pool()->allocate(size);
}
else {
return pool_p->allocate(size);
}
}
void pnew_delete(void *p)
{
Pool *hp = Pool::find_pool(p);
// note: if p == 0, then Pool::find_pool(p) will return 0.
if (hp) {
hp->deallocate(p);
}
}
// elsewhere...
class Obj {
public:
// misc ctors, dtors, etc.
// just a sampling of new/del operators
void *operator new(size_t s) { return pnew_new(s); }
void *operator new(size_t s, Pool *hp) { return pnew_new(s, hp); }
void operator delete(void *dp) { pnew_delete(dp); }
void operator delete(void *dp, Pool*) { pnew_delete(dp); }
void *operator new[](size_t s) { return pnew_new(s); }
void *operator new[](size_t s, Pool* hp) { return pnew_new(s, hp); }
void operator delete[](void *dp) { pnew_delete(dp); }
void operator delete[](void *dp, Pool*) { pnew_delete(dp); }
};
// elsewhere...
ClusterPool *cp = new ClusterPool(arg1, arg2, ...);
Obj *new_obj = new (cp) Obj(arg_a, arg_b, ...);
Maintenant, vous pouvez cluster objets réunis dans un seul mémoire de l'arène, sélectionnez un allocateur qui est très rapide, mais n'a pas de libération de la mémoire, l'utilisation du mappage de la mémoire, et tout autre sémantique que vous souhaitez imposer, par le choix de la piscine et de la passer en argument un objet de positionnement de l'opérateur new.
Je l'ai utilisé dans les programmes temps réel. En général, nous ne souhaitent effectuer toute allocation dynamique (ou de libération de la mémoire) après le démarrage du système, car il n'y a aucune garantie combien de temps cela va prendre.
Ce que je peux faire est préallouer une grande partie de la mémoire (suffisamment grand pour contenir n'importe quelle quantité de ce que la classe peut exiger). Ensuite, une fois que je figure à l'exécution la façon de construire les choses, de placement de nouvelles peuvent être utilisés pour construire des objets là où je veux. Une situation que je connais, je l'ai utilisé en était d'aider à créer un hetrogenious tampon circulaire.
C'est certianly pas pour la feinte de cœur, mais c'est pourquoi ils font de la syntaxe pour ça un peu ardu.