L’opérateur new ne reçoit pas d’octets supplémentaires

J’ai un tel code

#include  class Foo { int m_data; public : Foo() : m_data(0) { } /*~Foo() { }*/ static void* operator new[](const size_t size) { return malloc(size); } static void operator delete[](void* data) { free(data); } }; int main() { Foo* objects = new Foo[5]; delete [] objects; } 

Dans ce cas, je reçois une valeur de size dans la nouvelle surcharge d’opérateur de 20 octets que je voulais ( sizeof(int) * 5 ). Mais si je supprime le commentaire du destructeur, la size de 24 octets. Oui, je sais maintenant que ces octets supplémentaires sont utilisés pour stocker la taille de la mémoire allouée et sont égaux à sizeof(size_t) . Je ne comprends pas pourquoi je les ai seulement si je mets explicitement en œuvre destructor. Si je ne le fais pas, le compilateur devrait faire exactement la même chose ou je manque quelque chose?

J’ai essayé cela sur MSVS 2010 et 2012. Compilé pour Win32.

Les “octets supplémentaires” demandés par new[] à l’ operator new[] ne sont pas utilisés pour “stocker la taille de la mémoire allouée”, comme vous semblez le croire. Ils sont utilisés pour stocker le nombre d’éléments dans le tableau, de sorte que delete[] sache le nombre de destructeurs à appeler. Dans votre exemple, les destructeurs sont sortingviaux. Il n’y a pas besoin de les appeler. Il n’est donc pas nécessaire d’allouer ces octets supplémentaires et de stocker le nombre d’éléments.

La “taille de la mémoire allouée” (c’est-à-dire la taille du bloc en octets ) est une histoire complètement différente. Il est stocké et récupéré indépendamment par un allocateur de niveau inférieur – le malloc/free dans votre exemple.

En d’autres termes, en général, un bloc de mémoire alloué par new[] a deux jeux d’octets supplémentaires devant les données réelles: la taille de bloc en octets (introduite par malloc ) et le nombre d’éléments (introduit par new[] ). Le second est facultatif, comme le montre votre exemple. Le premier est généralement toujours présent, car il est atsortingbué de manière inconditionnelle par malloc . Par exemple, votre appel malloc allouera physiquement plus de 20 octets, même si vous n’en demandez que 20 . Malloc utilisera ces octets supplémentaires pour stocker la taille du bloc en octets.

Cette dernière se produit également dans votre exemple. Vous ne le voyez tout simplement pas, car cela se produit à l’intérieur du malloc .

Si le compilateur n’a pas besoin d’appeler le destructeur, il n’a pas besoin de se souvenir du nombre de destructeurs à appeler. Ce comportement ne serait pas observé si vous aviez un membre de données à détruire, comme std::ssortingng , car le compilateur aurait toujours besoin de le détruire.