2010-05-03 4 views
3

C++ je suis tombé sur cette ligne est Stroustrup An operator function must either be a member or take at least one argument of a user-defined type (functions redefining the new and delete operators need not).Surcharger nouveau, supprimer dans

opérateur Dont nouveau opérateur delete prendre un type défini par l'utilisateur comme l'un de leurs arguments? qu'est-ce que cela signifie, suis-je manque quelque chose ici

Répondre

3

Vous pouvez surcharger l'opérateur new global normal pour toutes les classes d'ajouter des fonctionnalités (par exemple, l'enregistrement ou la détection des fuites) si vous le désirez, mais il n'y a aucun moyen d'appeler l'ancien définition de l'opérateur new, donc vous serez probablement bloqué en appelant malloc() depuis l'intérieur de votre operator new redéfini pour obtenir réellement la mémoire dont vous avez besoin.

+0

Si cela surchargeait (ou même surchargeait) alors il y aurait un moyen d'appeler le 'new' global original. Ça ne surcharge pas. – wilhelmtell

+1

Il s'agit en fait de remplacer et de ne pas surcharger, donc une fois que vous avez fourni votre propre 'new' /' delete', il n'y a aucun moyen d'appeler les "originaux". –

5

La citation de Stroustrup s'applique apparemment à l'opérateur surchargeant. Le langage C++ prend en charge la surcharge de l'opérateur pour les types définis par l'utilisateur uniquement. Cela signifie que la fonction de surcharge (operator <something>) doit être soit un membre de type défini par l'utilisateur, soit une fonction autonome avec au moins un argument de type défini par l'utilisateur. C'est exactement ce que l'on entend par la citation en question.

Les fonctions operator new et operator delete autonomes (non membres) n'ont pas besoin de prendre en compte la valeur du type défini par l'utilisateur. Cela pourrait être vu comme quelque chose qui contredit votre citation.

Cependant, en réalité, il n'y a pas de contradiction. Ces opérateurs ne sont pas vraiment surchargé. Lorsque vous fournissez vos propres versions de operator new/operator delete autonome, vous êtes en réalité en remplacement de ceux fournis par la bibliothèque. Ceci est le terme officiel de la spécification de la langue: remplacement, pas surcharge. C'est pourquoi la citation ci-dessus ne s'applique pas vraiment à operator new et operator delete.

+0

'void * operator new (size_t, my_sandbox &)' est certainement une surcharge. Cependant, le chemin de recherche pour le membre de classe 'new' /' delete' est en dehors de la surcharge. – Potatoswatter

+0

Oui, mais ce que je voulais dire c'est que vous * pouvez * écrire votre propre version de "standard" 'operator new':' void * operator new (size_t) '. Celui-ci violera apparemment l'exigence présente dans la citation. Pourtant c'est légal. – AnT

+0

Désolé, 'my_sandbox' est un hareng rouge. 'void * operator new (size_t, int)' est aussi une surcharge. De plus, le "chemin de recherche" est un phrasé pauvre. 'new operator' est recherché dans la portée de la classe, en utilisant des règles de surcharge, qui se retrouvent dans la portée globale, où l'utilisateur peut remplacer la valeur par défaut. Mon point est que * les deux * surcharge et remplacement se produisent. En passant, voyez-vous quelque chose de mal avec ma réponse? – Potatoswatter

0

operator new et operator delete sont recherchés en fonction du type de l'opérande dans l'expression new ou delete, et des arguments supplémentaires à parenthétiques new. Ainsi, ils peuvent être surchargés (et operator newest sous réserve d'une résolution de surcharge), mais par un mécanisme différent de celui des autres opérateurs. (C++ 03 §13.5/5)

En travaillant avec de la mémoire brute, ils ne traitent jamais de pointeurs vers le type de classe client. operator new prend toujours un argument size_t (et éventuellement d'autres arguments, dont aucun ne doit être de type défini par l'utilisateur) et renvoie void *. operator delete prend toujours un argument void * et éventuellement un size_t, peu importe comment il a été recherché.

je peux penser à deux raisons:

  • Ils traitent de la mémoire brute, ne contenant pas un objet construit. C'est toujours une erreur pour operator new ou operator delete de tenter d'accéder à un objet dans le bloc de mémoire retourné. (Mémoire pas utilisé pour construire des objets, cependant, est juste jeu.)
  • Un membre de la classe operator new ou operator delete peuvent être multipliant et/ou quasi-héréditaire, telle que la void* en question ne peut pas être fait pour pointer vers le sous-objet non encore construit ou déjà détruit, par un voodoo.
+0

Expliquer downvote? – Potatoswatter

+0

Il n'est pas tout à fait clair comment il répond à la question réelle, en dépit de discuter des domaines connexes pertinents. Je n'aurais jamais baissé les bras, mais je n'aurais pas non plus voté contre. –

+0

Je suppose que je ne vais pas droit au but, mais j'aborde directement comment et pourquoi ils sont surchargés sans arguments de type définis par l'utilisateur. Je vois cela comme la question centrale ... peut-être qu'il me manque quelque chose. – Potatoswatter

2

a + b est juste du sucre syntaxique pour a.operator+(b) ou operator+(a, b). D'autre part, new Foo(x, y, z) n'est pas seulement du sucre syntaxique pour operator new(Foo, x, y, z) ou quelque chose comme ça. Il est plus compliqué:

void* address = operator new(sizeof(Foo)); // here is the behavior you can replace 
try { 
    new(address) Foo(x, y, z); 
} catch (...) { 
    operator delete(address); 
} 

Comme vous pouvez le voir, la fonction operator new alloue seulement la mémoire, qui est seulement la moitié de ce que l'opérateur ne fait new. À mon avis, il aurait été beaucoup plus logique d'avoir nommé cette chose allocate_memory ou quelque chose comme ça. Ce n'est certainement pas un opérateur comme operator+.