web-dev-qa-db-fra.com

C++ delete vector, objets, mémoire disponible

Je suis totalement confus quant à la suppression d'éléments en C++ Si je déclare un tableau d'objets et si j'utilise la fonction clear(). Puis-je être sûr que la mémoire a été libérée?

Par exemple : 

tempObject obj1;
tempObject obj2;
vector<tempObject> tempVector;

tempVector.pushback(obj1);
tempVector.pushback(obj2);

Puis-je appeler Clear pour libérer toute la mémoire? Ou dois-je parcourir plusieurs fois pour supprimer un par un?

tempVector.clear();

Si ce scénario est remplacé par un pointeur d'objets, la réponse sera-t-elle la même que ci-dessus?

vector<tempObject> *tempVector;
//Push objects....
tempVector->clear();
39
mister

Vous pouvez appeler clear et cela détruira tous les objets, mais cela ne libérera pas la mémoire. Faire une boucle à travers les éléments individuels n’aidera pas non plus (quelle action proposeriez-vous même pour prendre sur les objets?). Voici ce que vous pouvez faire:

vector<tempObject>().swap(tempVector);

Cela créera un vecteur vide sans mémoire allouée et l'échangera avec tempVector, libérant ainsi efficacement la mémoire.

C++ 11 a également la fonction shrink_to_fit, que vous pouvez appeler après l'appel de clear (), et qui réduirait théoriquement la capacité à la taille (qui est maintenant 0). Il s’agit toutefois d’une demande non contraignante et votre implémentation est libre de l’ignorer.

74

Il y a deux choses distinctes ici:

  1. durée de vie de l'objet
  2. durée de stockage

Par exemple:

{
    vector<MyObject> v;
    // do some stuff, Push some objects onto v
    v.clear(); // 1
    // maybe do some more stuff
} // 2

En 1, vous effacez v: cela détruit tous les objets stockés. Chaque destructeur est appelé, si vous en avez écrit un, et tout ce qui appartient à MyObject est maintenant publié .Cependant, le vecteur v a le droit de conserver le stockage brut au cas où vous le voudriez plus tard.

Si vous décidez d'insérer des éléments supplémentaires entre 1 et 2, vous gagnez du temps, car vous pouvez réutiliser l'ancienne mémoire.

En 2, le vecteur v sort du cadre: tous les objets que vous y avez insérés depuis 1 seront détruits (comme si vous aviez explicitement appelé clear), mais le stockage sous-jacent est également libéré (v ne sera plus disponible). ne le réutilise plus).


Si je modifie l'exemple pour que v devienne un pointeur, vous devez le supprimer explicitement, car le pointeur sortant de la portée à 2 ne le fait pas pour vous. Il vaut mieux utiliser quelque chose comme std::unique_ptr dans ce cas, mais si vous ne le faites pas et que v présente une fuite, le stockage alloué le sera également. Comme ci-dessus, vous devez vous assurer que v est supprimé et que l'appel de clear n'est pas suffisant.

20
Useless

vector::clear() ne libère pas la mémoire allouée par le vecteur pour stocker des objets; il appelle des destructeurs pour les objets qu'il contient. 

Par exemple, si le vecteur utilise un tableau comme magasin de sauvegarde et contient actuellement 10 éléments, l'appel de clear() appellera le destructeur de chaque objet du tableau, , mais le tableau de sauvegarde ne sera pas désalloué; sizeof(T) * 10 octets alloués au vecteur (au moins). size() sera 0, mais size() renvoie le nombre d'éléments dans le vecteur, pas nécessairement la taille du magasin de support.

En ce qui concerne votre deuxième question, vous devez désallouer avec new tout ce que vous allouez avec delete. En règle générale, vous ne maintenez pas de pointeur sur un vecteur pour cette raison. Il existe rarement (voire jamais) une bonne raison de le faire et vous empêchez le nettoyage du vecteur lorsqu'il quitte le champ d'application. Toutefois, l'appel de clear() agira toujours de la même manière, quelle que soit la manière dont elle a été allouée.

14
Ed S.

Si vous devez utiliser le vecteur encore et encore et que votre code actuel le déclare à plusieurs reprises dans votre boucle ou à chaque appel de fonction, il est probable que vous manquerez de mémoire. Je vous suggère de le déclarer à l'extérieur, de le passer comme pointeur dans vos fonctions et d'utiliser:

my_arr.resize()

Ainsi, vous continuez à utiliser la même séquence de mémoire pour vos vecteurs au lieu de demander chaque fois de nouvelles séquences . J'espère que cela vous a aidé . Remarque: le redimensionner à différentes tailles peut ajouter des valeurs aléatoires. Passez un entier tel que 0 pour les initialiser, si nécessaire.

0
user3715882