2010-03-09 14 views
18

Lorsque vous allouez un tableau en utilisant new [], pourquoi ne pouvez-vous pas connaître la taille de ce tableau à partir du pointeur? Il doit être connu au moment de l'exécution, sinon delete [] ne sait pas combien de mémoire libérer.Pourquoi n'est-il pas possible d'accéder à la taille d'un nouveau tableau [] 'd?

À moins qu'il me manque quelque chose?

+0

Un simple bon design n'a pas besoin de savoir - dans un cas complexe, vous devez faire vous-même beaucoup de gestion. Il y a généralement des fonctions de débogage pour votre compilateur qui vous le diront - mais si vous en avez besoin, votre design est probablement faux. –

+0

Je me suis souvent demandé pourquoi vous ne voyez jamais un allocateur qui ne connaît pas la taille, et exige qu'il soit passé à la suppression. car combien de fois avez-vous déjà réussi à supprimer un bloc de mémoire et à ne pas pouvoir calculer facilement sa taille? Je suppose qu'il ne doit jamais avoir vraiment été un avantage à la mise en œuvre d'un système avec cette limitation ... – matt

+0

Il serait probablement imposer des restrictions inutiles sur la mise en œuvre d'une telle opération de bas niveau. Après tout, vous saviez combien vous avez demandé quand vous avez alloué le tableau, donc il n'y a pas de besoin pressant de l'exécution pour pouvoir vous le dire. – UncleBens

Répondre

14

Dans une implémentation typique, la taille du bloc de mémoire dynamique est en quelque sorte stockée dans le bloc lui-même - c'est vrai. Mais il n'y a pas de moyen standard pour accéder à cette information. (Les implémentations peuvent fournir des moyens spécifiques d'implémentation pour y accéder). C'est comme ça avec malloc/free, c'est comme ça avec new[]/delete[].

En fait, dans une mise en œuvre typique des allocations de mémoire brute pour new[]/delete[] appels sont finalement traités par une paire spécifique à la mise en œuvre malloc/free -comme, ce qui signifie que delete[] n'a pas vraiment se soucier de la quantité de mémoire à désaffecter: simplement appelle cela interne free (ou quel que soit le nom), qui prend soin de cela.

Ce que delete[] doit savoir, c'est combien d'éléments détruisent dans les situations où le type d'élément de tableau a un destructeur non trivial. Et c'est ce que votre question est sur - le nombre d'éléments de tableau, pas la taille du bloc (ces deux ne sont pas les mêmes, le bloc pourrait être plus grand que nécessaire pour le tableau lui-même). Pour cette raison, le nombre d'éléments dans le tableau est normalement également stocké à l'intérieur du bloc par new[] et récupéré plus tard par delete[] pour effectuer la destruction de l'élément de tableau approprié. Il n'y a pas de façon standard d'accéder à ce numéro non plus.

(ce qui signifie que dans le cas général, un bloc de mémoire typique allouée par new[] sera indépendamment, stocker simultanément deux la taille de bloc physique en octets et le nombre d'élément de tableau. Ces valeurs sont stockées par différents niveaux de C++ mécanisme d'allocation de mémoire - allocateur de mémoire brute et new[] respectivement - et n'interagissent pas les uns avec les autres de quelque façon que ce soit). Cependant, notez que pour les raisons ci-dessus, le nombre d'éléments de tableau n'est normalement stocké que lorsque le type d'élément de tableau a un destructeur non trivial. C'est à dire. ce compte n'est pas toujours présent. C'est l'une des raisons pour lesquelles il n'est pas possible de fournir un moyen standard d'accéder à ces données: vous devez toujours le stocker (ce qui gaspille de la mémoire) ou restreindre sa disponibilité par type de destructeur (ce qui prête à confusion).

Pour illustrer ce qui précède, lorsque vous créez un tableau de int de

int *array = new int[100]; 

la taille du tableau (c.-à-100) est pas normalement stockées par new[] depuis delete[] ne se soucie pas de ce (int n'a pas de destructeur). La taille physique du bloc en octets (comme, 400 octets ou plus) est normalement stockée dans le bloc par l'allocateur de mémoire brute (et utilisé par la mémoire brute deallocator invoquée par delete[]), mais il peut facilement s'avérer être 420 pour certains raison spécifique à la mise en œuvre. Donc, cette taille est fondamentalement inutile pour vous, car vous ne pourrez pas en déduire la taille exacte du tableau d'origine.

+1

Oui, il se peut que l'allocateur de mémoire ne connaisse pas la taille du tableau, il peut avoir retourné un bloc de la taille disponible suivante la plus grande et ne se soucie même pas que vous ayez utilisé 75% de la mémoire. il. –

7

Vous pouvez très probablement y accéder, mais cela nécessiterait une connaissance intime de votre allocateur et ne serait pas portable. La norme C++ ne spécifie pas comment implémentations stocker ces données, donc il n'y a pas de méthode cohérente pour l'obtenir. Je crois que cela n'a pas été précisé, car différents répartiteurs voudront peut-être l'enregistrer de différentes façons à des fins d'efficacité.

+0

Encore, il serait cool que le standard ait spécifié un opérateur 'len (...)', donc il est possible d'obtenir la taille d'un tableau en utilisant cet opérateur (et les auteurs peuvent implémenter cet opérateur len comme ils le veulent). .. :( – smerlin

+4

@smelin N'est-ce pas ce que 'std :: vector <>' est pour? – KitsuneYMG

5

Il est logique que, par exemple, la taille du bloc alloué ne soit pas nécessairement la même taille que le tableau. Bien que it is true que new[] peut stocker le nombre d'éléments (appelant chaque destructeur d'éléments), il n'a pas à le faire car il ne serait pas nécessaire pour un destructeur vide. Il n'y a pas non plus de moyen standard (C++ FAQ Lite 1, C++ FAQ Lite 2) de mettre en œuvre où new[] stocke la longueur du tableau car chaque méthode a ses avantages et ses inconvénients. En d'autres termes, il permet des allocations aussi rapides que possible en ne spécifiant rien sur la mise en œuvre. (Si l'implémentation doit stocker la taille du tableau ainsi que la taille du bloc alloué à chaque fois, cela gaspille de la mémoire dont vous n'avez pas besoin).

3

Simplement dit, le standard C++ ne nécessite pas de support pour cela. Il est possible que si vous en savez assez sur les internes de votre compilateur, vous pouvez trouver comment accéder à cette information, mais cela serait généralement considéré comme une mauvaise pratique. Notez qu'il peut y avoir une différence dans la disposition de mémoire pour les tableaux alloués par tas et les tableaux alloués par pile. Rappelez-vous que ce dont vous parlez ici est essentiellement des tableaux de type C, même si new et delete sont des opérateurs C++ - et le comportement est hérité de C. Si vous voulez un "tableau" C++ taille, vous devriez utiliser la STL (par exemple std :: vector, std :: deque).

+0

Ouais, je n'utilise généralement pas les tableaux de style C - c'était juste une question générale comme ça (si c'était –