La surcharge new
et delete
Remarque: Cela ne traite que de la syntaxe de la surcharge new
et delete
, pas avec la mise en œuvre de ces opérateurs surchargés. Je pense que la sémantique de la surcharge new
et delete
méritent leur propre FAQ, dans le cadre du sujet de la surcharge d'opérateur je ne peux jamais faire justice.
Notions de base
En C++, quand vous écrivez une expression nouvelle, comme new T(arg)
deux choses se produisent lorsque cette expression est évaluée: Premier operator new
est invoquée pour obtenir de la mémoire brute, puis le constructeur approprié d' T
est appelée à transformer cette matière première en mémoire dans un objet valide. De même, lorsque vous supprimez un objet, le destructeur est appelé, et la mémoire est alors retourné à l' operator delete
.
C++ permet de tune de ces deux opérations: gestion de la mémoire et la construction/destruction de l'objet, à la mémoire allouée. Celui-ci est réalisé par la rédaction des constructeurs et destructeurs pour une classe. Affiner la gestion de la mémoire se fait par l'écriture de votre propre operator new
et operator delete
.
La première des règles de base de la surcharge d'opérateur – ne pas le faire – s'applique en particulier à la surcharge new
et delete
. Presque les seules raisons de surcharge de ces opérateurs sont des problèmes de performance et les contraintes de mémoire, et dans de nombreux cas, d'autres actions, comme les changements des algorithmes utilisés, fournira beaucoup plus coût/gain ratio que d'essayer de bidouiller la gestion de la mémoire.
Le C++ de la bibliothèque standard est livré avec un ensemble prédéfini new
et delete
opérateurs. Les plus importants sont:
void* operator new(std::size_t) throw(std::bad_alloc);
void operator delete(void*) throw();
void* operator new[](std::size_t) throw(std::bad_alloc);
void operator delete[](void*) throw();
Les deux premiers allouer/désallouer de la mémoire pour un objet, les deux derniers pour un tableau d'objets. Si vous fournissez vos propres versions de ces, ils vont pas la surcharge, mais remplacer celles de la bibliothèque standard.
Si vous surchargez operator new
, vous devriez toujours aussi surcharger la correspondance operator delete
, même si vous n'avez jamais l'intention de l'appeler. La raison en est que, si un constructeur lève au cours de l'évaluation d'une expression nouvelle, le système d'exécution sera le retour de la mémoire de l' operator delete
correspondant à l' operator new
qui a été appelée pour allouer de la mémoire pour créer l'objet. Si vous ne fournissez pas une correspondance operator delete
, la valeur par défaut est appelé, qui est presque toujours tort.
Si vous surchargez new
et delete
, vous devriez envisager de surcharger le tableau des variantes, trop.
Placement new
C++ permet de créer de nouvelles et supprimer des opérateurs à prendre des arguments supplémentaires.
Soi-disant placement nouveau permet de créer un objet à une certaine adresse qui est transmis à:
class X { /* ... */ };
char buffer[ sizeof(X) ];
void f()
{
X* p = new(buffer) X(/*...*/);
// ...
p->~X(); // call destructor
}
La bibliothèque standard est livré avec les surcharges appropriées de la nouvelle et supprimer des opérateurs pour cela:
void* operator new(std::size_t,void* p) throw(std::bad_alloc);
void operator delete(void* p,void*) throw();
void* operator new[](std::size_t,void* p) throw(std::bad_alloc);
void operator delete[](void* p,void*) throw();
Notez que, dans l'exemple de code pour le placement de nouvelles données ci-dessus, operator delete
n'est jamais appelée, à moins que le constructeur de X déclenche une exception.
Vous pouvez aussi surcharger new
et delete
avec d'autres arguments. Comme avec l'argument supplémentaire pour le placement de nouveaux, ces arguments sont également répertoriés entre parenthèses après le mot-clé new
. Simplement pour des raisons historiques, ces variantes sont aussi souvent appelés placement nouvelles, même si leurs arguments ne sont pas pour placer un objet à une adresse spécifique.
Spécifiques à la classe new et delete
Plus couramment, vous souhaitez affiner la gestion de la mémoire parce que la mesure a montré que les instances d'une classe spécifique ou d'un groupe de classes associées, sont créés et détruits souvent et que par défaut, la gestion de la mémoire du système d'exécution, à l'écoute pour la performance générale, traite de façon inefficace dans ce cas précis. Pour améliorer cela, vous pouvez surcharge de new et delete pour une classe spécifique:
class my_class {
public:
// ...
void* operator new();
void operator delete(void*,std::size_t);
void* operator new[](size_t);
void operator delete[](void*,std::size_t);
// ...
};
Surchargé par conséquent, de nouvelles et de suppression se comportent comme des fonctions membres statiques. Pour les objets d' my_class
, std::size_t
argument sera toujours sizeof(my_class)
. Cependant, ces opérateurs sont également appelés pour les objets alloués dynamiquement des classes dérivées, auquel cas il pourrait être plus que cela.
Mondial de new et delete
À la surcharge de la global new et delete, il suffit de remplacer le pré-défini les opérateurs de la bibliothèque standard, avec notre propre. Cependant, c'est rarement qui doit être fait.