Je fais une partie et j'ai un vecteur de balles voler. Lorsque la balle est terminée, je fais des balles.erase (balles.begin () + i); Puis la balle disparaît. Cependant, cela n'entre pas pour obtenir la tige de la mémoire. Si je crée 5000 balles, créez 5 000 points de plus après ceux qui meurent, la mémoire reste la même, mais si je crée 5 000 de plus, tandis que ces 5 000 volent, il allouera un nouvel espace. Que dois-je faire pour libérer cette mémoire? P>
6 Réponses :
C'est la manière dont le modèle d'allocation de mémoire de la mémoire de vecteur se comporte de manière à fournir une opération push_back code>, il essaie essentiellement de deviner que vous voudrez peut-être remplir la partie effacée avec un nouvel élément afin que cela ne puisse pas " t libérer la mémoire. En faisant cela, cela peut éviter une allocation et des réparations constantes. Pour faire le tour de cela, vous pouvez utiliser le truc d'échange pour libérer la mémoire vectorielle inutilisée. Vous devez échanger votre vecteur vide avec un vecteur temporaire Sans nom de sorte que lorsque le vecteur temporaire soit hors de portée, il libère la mémoire dans son destructeur, quelque chose comme:
vecteur
C'est un hack bien connu. Par design, les vecteurs ne se contractent pas seuls.
Y a-t-il une stl qui peut faire ce que je veux?
C'est un piratage aussi bien connu qu'elle s'appelle un «idiome»;) Voir ceci: gotw.ca/ gotw / 054.htm
@ user146780: Si vous êtes vraiment inquiet pour l'utilisation de la mémoire et que vous ne voulez pas faire cela, vous pouvez essayer d'utiliser std :: deque code> car il fournit une meilleure gestion de la mémoire
@Dan: J'aime ça. Je pense que je vais le voler: "Non, patron, ce n'est pas un piratage, c'est un idiome."
@Steven Sudit: Un piratage documenté sur diverses encyclopédies et mentionné par divers gourous avec un nom clair et établi ... n'est pas vraiment un piratage plus longtemps :)
@Matthieu: C'est toujours un hack: vous faites de la vecteur faire quelque chose qu'il n'a pas été conçu pour faire. Si le vecteur ne faisait pas partie de la bibliothèque standard, l'approche sensionnelle serait d'ajouter une méthode .shrink ().
@Naveen: Je viens de remarquer que vous utilisez le mauvais idiome. Il devrait être vecteur
c.shrink () code> être plus clair? Ce que vous avez écrit serait alors
c.cclear (). Rétrécir () code> peut-être.
@Dan: Je suis d'accord que rétractable code> serait mieux ... mais je ne suis pas d'accord sur le nom "Hack". Je pense que nous devrons simplement accepter de ne pas être d'accord sur ce point.
@Matthieu: Peut-être que je suis d'accord avec vous que ce n'est pas un hack. L'argument de Sutter selon lequel vide code> ne devrait pas être une fonction de membre s'appliquerait à
rétrécir code> aussi - gotw.ca/gotw/084.htm (scanner jusqu'à" dans la mêlée "). Et pourquoi la peine de rédiger une fonction non membre et non ami pour quelque chose d'aussi simple que
intveec (c) .swap (c) code>?
Premier, STD :: La méthode d'effacement de vecteur n'est pas très efficace, il doit déplacer tous les articles après le supprimé. Si l'ordre des éléments vectoriels (balles) n'a pas d'importance, l'échange de la balle supprimée avec la dernière balle et la suppression de la dernière balle sera plus rapide (vous obtenez donc une complexité constante au lieu de la complexité linéaire). P>
second, quel est le problème réel - qu'après suppression des 10 000 articles, la mémoire n'est pas libérée? Parlons-nous de la mémoire libre rapportée par le système d'exploitation ou de l'espace libre sur le tas? Il est possible (et très probable), qu'un autre objet a été attribué après la position des données du vecteur, il n'est donc pas possible de simplement libérer cette mémoire au système d'exploitation; Mais il peut être réutilisé pour d'autres objets nouvellement créés. P>
Le Le Habituellement, lorsque les tailles utilisées et réservées sont identiques et que vous essayez d'insérer un nouvel élément, le vecteur allouera un nouveau tampon interne de deux fois la taille réservée précédente et copier tout l'existant éléments dans ce tampon. Ceci est transparent pour vous, sauf qu'il invalidera tout itérateur que vous tenez. Comme je l'ai noté auparavant, Afaik, la plupart des implémentations STL ne réduiront jamais la taille réservée comme une réponse à une effondrement. P> Malheureusement, pendant que vous pouvez forcer un vecteur à augmenter em> sa taille réservée Utilisation de la méthode Qu'est-ce que cela va faire est de créer un vecteur temporaire qui est une copie du vecteur d'origine (mais avec la capacité minimale nécessaire), puis échangez les tampons internes des deux vecteurs. Cela fera que votre vecteur d'origine ait les mêmes données, mais une taille réservée potentiellement plus petite. P> MAINTENANT, car la création de cette copie temporaire est une opération relativement coûteuse (c'est-à-dire qu'il prend beaucoup plus de temps de processeur que les lectures normales / Insertions / suppressions), vous ne voulez pas le faire à chaque fois que vous effacez un élément. Pour la même raison, c'est pourquoi le vecteur double sa taille réservée plutôt que de l'augmenter de 1 lorsque vous devez dépasser la taille existante. Par conséquent, ce que je recommanderais, c'est qu'après avoir effacé un nombre relativement important d'éléments, et vous savez que vous n'aurez pas ajouté que beaucoup plus de temps à tout moment, effectuez l'échange «Trick» ci-dessus pour réduire la capacité. P> Enfin, vous voudrez peut-être aussi envisager d'utiliser autre chose qu'un std :: vecteur code> classe gère automatiquement sa mémoire interne. Il se développera pour contenir autant d'articles que vous y constaterez, mais en général, il ne se rétrécira pas à lui-même lorsque vous supprimez les objets (bien que cela libère bien sûr la mémoire lorsqu'elle détruit).
STD :: Vecteur code> a deux concepts pertinents de "taille". Premièrement est la taille "réservée", quelle est la quantité de mémoire qu'il a allouée à partir du système à utiliser pour stocker des éléments vectoriels. La seconde est la taille "utilisée", qui est combien d'éléments sont logiquement dans le vecteur. Clairement, la taille réservée doit être au moins aussi grande que la taille d'occasion. Vous pouvez découvrir la taille d'occasion avec la méthode
Taille () CODE> (que je suis sûr que vous savez déjà), et vous pouvez découvrir la taille réservée à l'aide de la capacité
Capacité () Code> . p>
Réservez () CODE>, cela ne fonctionne pas pour décroissant em> la capacité réservée. Pour autant que je sache, votre meilleur choix pour effectuer une réduction de la capacité consiste à effectuer les éléments suivants: p>
std :: vecteur code> pour cela. Eléments d'effacement du milieu d'un vecteur, qu'il semble que vous faites fréquemment, est une opération lente par rapport à de nombreux autres types de structures de données (car le vecteur doit copier tous les éléments suivants en arrière d'une fente pour remplir le trou) . Quelle structure de données est la meilleure pour vos besoins dépend de ce que vous faites d'autre avec les données. P> p>
+1 pour que le point sur l'effacement du milieu soit coûteux, ainsi que l'exhaustivité de cette réponse.
myvector.swap (std :: vecteur
std :: vecteur
@Fred merci, vous avez complètement raison. Je l'ai écrit dans l'autre sens parce qu'il semble plus facile de suivre ce qui se passe de cette façon, mais oublié cette mise en garde. Fixé.
Il convient probablement de noter que la raison redimensionne est si chère est que std :: vecteur code> garantit que les éléments sont stockés dans des emplacements de stockage contigus de la même manière qu'un tableau est.
Je vous suggère de jeter un coup d'œil à ces deux idiomes et de choisir celui qui vous convient le plus:
Rétrécira
Clear & Minimiser P>
+1 Pour mettre les noms sur les idiomes, il est plus facile de mémoriser et de communiquer.
Merci, ce livre btw est doré :)
Cela peut ne pas se débarrasser de la mémoire.
Mais la prochaine fois que vous devez ajouter un bullit, il n'a pas besoin de réaffecter plus d'espace.
Il ne réutilisera pas la mémoire que la balle effacée est venue. P>
note:
Si vous effacez du milieu d'un conteneur relativement souvent, le vecteur peut ne pas être le conteneur correct. Ceci est parce que si vous retirez l'élément N, tous les éléments de [N + 1, finissent) doivent être déplacés d'un espace en mémoire. P>
Lorsque la balle est terminée, je fais des balles.Aser (balles.begin () + i); p>
Ne faites pas ça. Si plusieurs balles sont finies par image, vous obtenez des performances horribles, car les balles qui ne sont pas finies seront copiées sur et sur une fois, ce qui n'est vraiment pas nécessaire. Voici ce que je ferais: p>
xxx pré> Cette approche ne bouge que chaque balle vivante une fois. P> blockquote>
Comment allez-vous le faire? STL, Boost, Roll-Vos propres ou autre chose?
Vous pouvez utiliser
std :: vecteur :: redized () code> pour rétrécir la taille. Voir Cplusplus.com/reference/stl/vector/resize
@THOMAS: Cela rétrécira la taille mais pas la capacité. La quantité de mémoire allouée ne changerait pas.