Comment fonctionne le tas en C ++

La tas

Sommaire

est un bloc amorphe de mémoire que votre programme C ++ peut accéder si nécessaire. En savoir plus sur pourquoi il existe et comment l'utiliser.

De même qu'il est possible de faire passer un pointeur à une fonction, il est possible pour une fonction de retour à un pointeur. Une fonction qui renvoie l'adresse d'un double est déclaré comme suit:

double * fn (void) -

Cependant, vous devez être très prudent lors du retour d'un pointeur. Pour comprendre les dangers, vous devez savoir quelque chose sur la portée des variables.

Portée limitée en C ++

Sfaire face est la plage sur laquelle une variable est définie. Considérons le code suivant:

// La variable suivante est accessible à toutes les fonctions // et défini tant que le programme est en marche // (portée globale) int intGlobal - // l'intChild variable suivante est accessible // seulement à la fonction et est défini uniquement // aussi longtemps que C ++ est l'exécution de l'enfant () ou une fonction // quel enfant () appelle (portée de la fonction) enfant void (void) {int intChild -} // l'intParent variable suivante a la fonction // parent scopevoid (void) {int intParent = 0-enfant () - int intLater = 0-intParent = intLater-} int main (int nargs, char * pargs []) {parent () -}

Ce fragment de programme commence par la déclaration d'une variable intGlobal. Cette variable existe à partir du moment où le programme commence l'exécution jusqu'à ce qu'elle se termine. Vous dites que intGlobal “ a la portée du programme n ° 148. Vous dites aussi que la variable “ entre dans la portée ” avant même que la fonction main () est appelé.

La fonction main () invoque immédiatement parent(). La première chose que le processeur voit dans parent() est la déclaration de intParent. À ce moment, intParent va dans la portée - qui est, intParent est défini et disponible pour le reste de la fonction parent().




La deuxième déclaration parent() est l'appel à enfant (). Encore une fois, la fonction enfant () déclare une variable locale, cette fois intChild. La portée de la variable intChild est limitée à la fonction enfant (). Techniquement, intParent est pas définie dans le champ de enfant () car enfant () ne pas avoir accès à intParent- Cependant, la variable intParent continue d'exister tout enfant () est l'exécution.

Quand enfant () les sorties, la variable intChild est hors de portée. Non seulement est- intChild plus accessible, il ne existe plus. (La mémoire occupée par intChild est retourné à la réserve générale pour être utilisé pour d'autres choses.)

Comme parent() continue l'exécution, la variable intLater va dans la portée à la déclaration. Au point que parent() revient à main (), les deux intParent et intLater sont hors de portée.

Car intGlobal est déclarée globalement, dans cet exemple, il est disponible à tous les trois fonctions et reste disponible pour la durée du programme.

L'examen du problème de la portée en C ++

Le segment de code suivant compile sans erreur, mais ne fonctionne pas (ne vous détestez pas juste que?):

double * enfant (void) {deux dLocalVariable-retour dLocalVariable-} parent (void) {double * pdLocal-pdLocal = enfant () - * pdLocal = 1.0-}

Le problème de cette fonction est que dLocalVariable est définie uniquement dans le cadre de la fonction enfant (). Ainsi, au moment où l'adresse de mémoire de dLocalVariable est retourné à partir de enfant (), elle fait référence à une variable qui a disparu. La mémoire qui dLocalVariable anciennement occupé est probablement utilisée pour autre chose.

Cette erreur est très commun, car il peut se glisser dans un certain nombre de façons. Malheureusement, cette erreur ne provoque pas le programme pour arrêter instantanément. En fait, le programme peut fonctionner très bien la plupart du temps - qui est, le programme continue de travailler aussi longtemps que la mémoire anciennement occupé par dLocalVariable ne sont pas réutilisés immédiatement. Ces problèmes intermittents sont les plus difficiles à résoudre.

Fournir une solution utilisant le tas en C ++

Le problème de la portée originaire parce C ++ a repris la mémoire définie localement avant le programmeur était prêt. Ce qui est nécessaire est un bloc de mémoire commandé par le programmateur. Elle peut affecter la mémoire et le remettre quand elle veut - pas parce que C ++ pense qu'il est une bonne idée. Un tel bloc de mémoire est appelé le tas.

Mémoire Heap est allouée à l'aide de la nouveau mot-clé suivi par le type d'objet à allouer. La nouveau commande rompt un morceau de la mémoire hors tas assez grand pour contenir le type d'objet spécifié et renvoie son adresse. Par exemple, ce qui suit alloue un double variables hors du tas:

double * enfant (void) {deux pdLocalVariable = new double retour pdLocalVariable- *}

Cette fonction fonctionne désormais correctement. Bien que la variable pdLocalVariable est hors de portée lorsque la fonction enfant () les rendements, la mémoire à laquelle pdLocalVariable se réfère ne fonctionne pas. Un emplacement de mémoire renvoyée par nouveau ne va pas hors de portée jusqu'à ce qu'il soit explicitement renvoyé au tas en utilisant le mot-clé effacer, qui est spécialement conçu à cet effet:

parent void (void) {// enfant () renvoie l'adresse d'un bloc // des tas memorydouble * pdMyDouble = enfant () - // stocker une valeur il pdMyDouble * = 1,1 - // ... // maintenant retourner le mémoire à l'heapdelete pdMyDouble-pdMyDouble = 0 - // ...}

Ici, le pointeur renvoyé par enfant () est utilisé pour stocker une valeur double. Une fois la fonction terminée avec l'emplacement de mémoire, il est renvoyé à la pile. La fonction parent() définit le pointeur à 0 après la mémoire du tas a été retourné - ce ne est pas une exigence, mais il est une très bonne idée.

Si le programmateur tente par erreur pour stocker dans quelque chose * PdMyDouble après le effacer, le programme se bloque immédiatement avec un message d'erreur significatif.

Tu peux utiliser nouveau à allouer des tableaux dans le tas aussi bien, mais vous devez retourner un tableau en utilisant la effacer[] mot-clé:

int * nArray = new int [10] -nArray [0] = 0-delete [] nArray-

Techniquement new int [10] invoque la nouvelle [] opérateur, mais il fonctionne de la même que nouveau.


» » » » Comment fonctionne le tas en C ++