7
votes

C ++ - Allocation de mémoire sur le tas en utilisant "nouveau"

Si j'ai la déclaration suivante:

int * x = neuf int;

Dans ce cas, j'ai alloué la mémoire sur le tas de manière dynamique. En d'autres termes, je dispose maintenant d'une adresse de mémoire réservée pour un objet int .

Dites après cela que j'ai fait ce qui suit:

Supprimer x;

ce qui signifie que je libéré l'adresse de la mémoire sur le tas.

Dites après cela, je suis à nouveau suivi:

int * x = neuf int;

x pointer sur la idée identique une adresse de mémoire ancienne indiquée sur le tas avant d'être supprimée?

Et si je l'avais fait précédemment Supprimer :

x = null;

et, alors a fait ceci:

int * x = neuf int;

x pointer sur une adresse mémoire sur le tas autre que l'ancien?

Merci.


1 commentaires

En définissant simplement un pointeur sur null , vous ne le supprimez pas. Si vous faites alors neuf int , l'ancienne mémoire sera toujours utilisée (sans pointeur - c'est une fuite de mémoire) et bien sûr nouveau toujours Pointez sur une adresse nouvelle - d'où le nom.


6 Réponses :


1
votes

Non, il n'y a pas de garantie de ce type. Cela dépend entièrement de l'allocateur utilisé pour satisfaire votre demande de mémoire. Cependant, C ++ étant la puissante bête que c'est, laissez-vous remplacer le nouvel opérateur. Vous pouvez créer un allocator personnalisé (gestion de la mémoire) qui fournit une mémoire d'une certaine manière, ce qui est parfois très utile.


3 commentaires

Pourriez-vous donner un exemple - comment allouer une mémoire sans utiliser nouveau et quel est un allocator personnalisé utilisé?


Les allocateurs personnalisés peuvent être utilisés pour fournir une quantité fixe de mémoire séquentielle. Performance sage et généralement dans les jeux, il est préférable d'avoir un bon nombre d'accès à la mémoire séquentielle. Un collecteur à ordures (gestion automatique de la mémoire) le fournit généralement en allouant cela rapproché ensemble dans le temps. Un simple allocateur linéaire pourrait faire la même chose et peut également déplacer des objets sur un petit tas lorsque les choses sont supprimées pour prévenir les trous et prendre en compte les autres contraintes matérielles pour améliorer les performances de la mémoire.


Pour plus d'exemples, vous pouvez voir cette page cgrogramming.com/tatudial/operator_new.html i Je suis tout à fait sûr qu'il est possible de remplacer l'allocator par défaut, par lequel vous remplaceriez la nouvelle opération neuf int .



1
votes

Non, le pointeur est retourné du deuxième neuf int; peut pointer n'importe où dans la tenue d'adresse écritable valide. Il n'est pas garanti que la région précédemment traitée sera utilisée (en fait, la plupart des temps, il peut ne pas choisir de choisir la mémoire réelle à un moment donné ultérieur).


0 commentaires

2
votes

Lorsque vous faites cela avant de supprimer: xxx

alors c'est une fuite de mémoire . Vous perdez de la mémoire qui ne sert rien et que vous ne pouvez pas libérer parce que vous avez perdu l'adresse. (Vous pouvez supprimer un pointeur NULL, il ne fait que rien)

Faire cela trop de temps peut entraîner un accident de système / ralentissement de plusieurs personnes acceptables car toute votre mémoire est gaspillée. (Utiliser trop d'échange sur le disque, etc ... etc ...)

Ne vous attendez pas à obtenir la même nouvelle adresse exacte après une suppression, puis une nouvelle nouvelle. Bien que cela puisse arriver de temps en temps, au hasard.


0 commentaires

1
votes

1) Après votre libre libre, si vous allouez à nouveau en utilisant la même variable, il n'y a aucune garantie que vous allez obtenir le même morceau de mémoire. Pensez à la manière dont la nouvelle est mise en œuvre, cela peut être fait de n'importe quelle manière que vous pouvez imaginer même en utilisant des allocateurs personnalisés. En outre, il est possible que d'autres threads utilisaient de nouvelles appels entre () et nouveaux () et «volent» votre mémoire

2) Ne le faites pas. Vous perdez une référence et si vous appliquez l'opérateur Supprimer sur NULL POINTER, cela ne fera rien. Donc, vous pourriez avoir une fuite de ressources si vous ne stockez pas la référence sur une autre variable. Si vous appelez nouveau à nouveau, cela allouera certainement ailleurs en supposant que personne n'a été traitée la zone accordée par le premier nouveau ()


0 commentaires

11
votes

Dans le premier cas, vous peut-être obtenir le même bloc de mémoire, mais il n'y a aucune certitude de cela.

Dans le second cas, puisque vous n'avez pas libéré la mémoire, il y a une quasi-certitude que vous obtiendrez un bloc de mémoire différent à une adresse différente. Il y a des collectionneurs de déchets de C ++. Si vous en avez utilisé l'un d'entre eux, il est concevable que le collecteur des ordures fonctionne entre le moment où vous avez annulé le pointeur (vous n'avez donc plus accès au bloc de mémoire alloué précédemment) et de demander une allocation à nouveau. Dans un tel cas, vous pourriez à nouveau obtenir le même bloc de mémoire. Bien sûr, sans collectionneur de déchets, vous venez de fuir la mémoire, vous n'avez donc pas un moyen de le faire en tout cas.


0 commentaires

3
votes

Ce que vous demandez est tout à fait indéfini (conformément à la norme C / C ++) et dépend de la mise en œuvre.

Il convient de vous convaincre de la tester avec votre version du compilateur.

Ce que vous devez noter, cependant, c'est de ne jamais dépendre du résultat de ce comportement car il peut changer de temps / avec n'importe quel système d'exploitation / même une mise à niveau de votre compilateur.

Quant à ce que je pense peut-être arriver, vous obtiendrez la même adresse probablement, à moins que vous n'ayez d'autres threads dans votre programme qui allouent également en même temps. Mais même vous pourriez avoir la même adresse, si la mise en œuvre MALLOC particulière de votre compilateur décide d'utiliser différents tas pour différents threads (ce qui est meilleur en termes de perf)


0 commentaires