Tout d'abord, il y a vraiment un certain nombre de différents new
et delete
opérateurs (un nombre arbitraire, vraiment).
Tout d'abord, il y a ::operator new
, ::operator new[]
, ::operator delete
et ::operator delete[]
. Deuxièmement, quelle que soit la classe X
, il y a X::operator new
, X::operator new[]
, X::operator delete
et X::operator delete[]
.
Entre eux, c'est beaucoup plus courant de surcharge de la classe spécifique des opérateurs que les opérateurs globaux -- il est assez commun pour l'utilisation de la mémoire d'une classe particulière de suivre une assez spécifique de modèle, vous pouvez écrire des opérateurs qui fournissent des améliorations substantielles sur les valeurs par défaut. Il est généralement beaucoup plus difficile de prévoir l'utilisation de la mémoire presque exactement ou, plus spécifiquement, sur une base globale.
C'est probablement aussi la peine de mentionner que même si operator new
et operator new[]
sont séparés les uns des autres (de même pour n'importe quel X::operator new
et X::operator new[]
), il n'y a pas de différence entre les exigences pour les deux. On va être invoquées pour allouer un objet unique, et l'autre pour allouer un tableau d'objets, mais chacun reste juste reçoit une quantité de mémoire nécessaire, et doit renvoyer l'adresse d'un bloc de mémoire (au moins) que les grands.
Parlant des exigences, il est probablement judicieux de revoir les autres exigences1: les opérateurs globaux doivent être véritablement mondial -- vous ne pouvez pas mettre l'un à l'intérieur d'un espace de noms ou de prendre un statique dans une unité de traduction. En d'autres termes, il n'existe que deux niveaux qui surcharge peut avoir lieu: une classe spécifique de la surcharge globale ou de surcharge. Dans l'entre-deux points tels que "toutes les classes dans l'espace de noms X" ou "toutes les attributions dans l'unité de traduction de Y" ne sont pas autorisés. La classe des opérateurs spécifiques sont nécessaires pour être static
- mais vous n'êtes pas vraiment nécessaire de les déclarer comme statique -- ils vont être statique si vous avez explicitement déclarer static
ou pas. Officiellement, les opérateurs globaux beaucoup de retour de la mémoire aligné de sorte qu'il peut être utilisé pour un objet de type quelconque. Officieusement, il y a un peu wiggle-chambre à un égard: si vous recevez une demande d'un petit bloc (par exemple, 2 octets) vous avez seulement besoin de fournir de la mémoire aligné pour un objet de cette taille, depuis la tentative de stocker quoi que ce soit plus il y aurait de conduire à un comportement indéfini de toute façon.
Ayant couvert ces préliminaires, nous allons revenir à la question initiale sur pourquoi vous voulez à la surcharge de ces opérateurs. Tout d'abord, je dois souligner que les raisons pour surcharger les opérateurs mondiaux ont tendance à être considérablement différents de la des raisons de surcharge de la classe des opérateurs spécifiques.
Comme il est plus courant, je vais vous parler de la classe des opérateurs spécifiques à la première. La raison principale de la classe de gestion de la mémoire est la performance. Cela vient généralement dans les deux (ou les deux) des deux formes: soit l'amélioration de la vitesse ou de la réduction de la fragmentation. La vitesse est améliorée par le fait que le gestionnaire de mémoire sera seulement traiter avec des blocs d'une taille particulière, de sorte qu'il peut retourner à l'adresse d'un bloc libre plutôt que de passer tout le temps de vérifier si un bloc est assez grand, la division d'un bloc en deux si elle est trop grande, etc. La Fragmentation est réduit de (surtout) de la même manière, par exemple, de pré-allocation d'un bloc assez grand pour N objets donne exactement l'espace nécessaire pour N objets; allouer un objet de mémoire allouer exactement l'espace d'un objet, et pas un seul octet de plus.
Il y a une grande variété de raisons pour surcharger la mémoire globale de gestion des opérateurs. Beaucoup de ces derniers sont orientés vers le débogage ou de l'instrumentation, telles que le suivi de la quantité totale de mémoire requises par une application (par exemple, en préparation pour le portage d'un système embarqué), ou le débogage des problèmes de mémoire en montrant l'inadéquation entre l'allocation et la libération de la mémoire. Une autre stratégie consiste à allouer de la mémoire supplémentaire avant et après les limites de chaque bloc, et l'écriture des modèles uniques dans ces domaines. À la fin de l'exécution (et éventuellement d'autres fois aussi), ces domaines sont examinés pour voir si le code est écrit en dehors de la alloués limites. Pourtant, une autre est de tenter d'améliorer la facilité d'utilisation en automatisant au moins certains aspects de l'allocation de mémoire ou de suppression, comme avec un automatisée garbage collector.
Une non-valeur par défaut global d'allocation peut être utilisé pour améliorer les performances. Un cas typique serait de remplacer une valeur par défaut de l'allocateur qui était juste lent en général (p. ex., au moins certaines versions de MS VC++ autour de 4.x pourrait appeler le système HeapAlloc
et HeapFree
fonctions pour chaque affectation, l'opération de suppression). Une autre possibilité que j'ai vu, dans la pratique, a eu lieu sur les processeurs Intel lors de l'utilisation de l'ESS opérations. Ceux-ci opèrent sur des données 128-bit. Alors que les opérations de travail, indépendamment de l'alignement, la vitesse est améliorée lorsque les données sont alignées à 128 bits limites. Certains compilateurs (par exemple, MS VC++ nouveau2) n'ont pas nécessairement appliquées à l'alignement que plus de limite, de sorte que même si le code à l'aide de la valeur par défaut de l'allocateur, en remplacement de l'allocation pourrait fournir une substantielle amélioration de la vitesse pour ces opérations.
- La plupart des besoins sont couverts dans le §3.7.3 et l'article 18.4 de la norme C++ (ou §3.7.4 et §de 18,6 dans C++0x, à moins que de N3291).
- Je me sens obligé de souligner que je n'ai pas l'intention de s'en prendre à Microsoft compilateur -- je doute qu'il a un nombre inhabituel de ces problèmes, mais il m'arrive de l'utiliser beaucoup, donc j'ai tendance à être tout à fait conscient de ses problèmes.