"Bonne" façon de libérer un std::vector objet

la première solution est:

std::vector<int> *vec = new std::vector<int>;
assert(vec != NULL);
// ...
delete vec;

autres est:

std::vector<int> v;
//...
vec.clear();
vec.swap(std::vector<int>(vec));

La deuxième solution est un peu un truc --- quelle est la "bonne" façon de faire?

mise à Jour:

je suis conscient que le destructeur sera appelé une fois qu'il est hors de la pile, j'étais curieux au sujet d'autres méthodes.

32
demandé sur Jacob 2010-06-16 19:08:25

12 réponses

Le plus simple et le plus fiable pour désallouer un vecteur est à déclarer sur la pile et tout simplement ne rien faire.

void Foo() {
  std::vector<int> v;
  ...
}

C++ garantit que le destructeur de v sera appelée lorsque la méthode s'exécute. Le destructeur d' std::vector va s'assurer que toute mémoire qu'il alloue est libérée. Tant que l' T type vector<T> a une bonne sémantique de désallocation C++ tout ira bien.

34
répondu JaredPar 2010-06-16 15:11:48

la façon la plus simple de désallouer tout le stockage dans un vecteur, sans détruire l'objet vecteur lui-même, est

vec = std::vector<int>();

Votre deuxième variante aura le même effet, mais il saute à travers plus de cerceaux sur le chemin. Le truc" copier et échanger " désalloue toute capacité supplémentaire dans le vecteur, et peut être utile s'il contient certaines données que vous voulez conserver. Si il n'y a pas de données, alors il n'y a pas besoin de copier ou d'échange.

15
répondu Mike Seymour 2010-06-16 16:45:32
std::vector<int> vi;
/*push lots of stuff into the vector*/

// clean it up in C++03
// no need to clear() first
std::vector<int>().swap(vi);

// clean it up in C++0x
// not a one liner, but much more idiomatic
vi.clear();
vi.shrink_to_fit();
12
répondu deft_code 2010-06-16 15:23:32

je suis d'accord avec Mike Seymour essayez cela, vous remarquerez que la dernière fonctionne bien

const int big_size = 10000;
vector<double> v( big_size );
cout << "Before clearing, the capacity of the vector is "
  << v.capacity() << " and its size is " << v.size();
v.clear();
cout << "\nAfter clearing, the capacity of the vector is "
  << v.capacity() << " and its size is " << v.size();
vector<double>().swap( v );

cout << "\nAfter swapping, the capacity of the vector is "
  << v.capacity() << " and its size is " << v.size();

vector<double> v1( big_size );
v1 = vector<double>();
cout << "\n After vector<double>();, the capacity of the vector is "
  << v1.capacity() << " and its size is " << v1.size();
3
répondu Sam 2016-02-09 20:28:28

N'utilisez pas les fonctions d'allocation de mémoire sauf si vous en avez vraiment besoin. Si votre classe a besoin d'un vecteur, toujours, il suffit d'ajouter le membre std::vector directement. Pas besoin de faire l'attribution de mémoire ici.

dans les cas où vous avez besoin du vecteur dynamique, l'allouer et la supprimer comme dans votre premier exemple est correct à 100%.

dans le second exemple, l'appel à std::swap est strictement parlé non nécessaire, parce que la méthode claire va effacer le vecteur, le rendant vide. Un le problème possible est qu'il n'y a aucune garantie que le vecteur libérera réellement la mémoire, la redonnant au système d'exploitation (ou à la durée d'exécution). Le vecteur peut garder la mémoire allouée juste au cas où vous remplissez le vecteur de droite après l'effacer. L'appel à std:: swap peut être une astuce pour "forcer" le vecteur à libérer ses données internes, mais il n'y a aucune garantie que cela se produira réellement.

1
répondu Patrick 2010-06-16 15:17:00

a mon avis, vous avez un vecteur qui contient temporairement une grande quantité de données. Une fois que le vecteur a été éliminé, il prendra encore toute cette mémoire. Vous voulez libérer cette mémoire une fois que vous en avez fini avec elle, mais vous n'avez pas terminé la fonction/l'objet avec lequel vous travaillez.

Solutions dans l'ordre décroissant de préférence:

  1. retravailler le code de façon à ce que le vecteur utilisant le code soit dans son propre bloc/fonction/objet de façon à ce qu'il soit détruit naturellement
  2. utilisez le Trick swap, de cette façon vous n'avez pas à vous soucier de vous assurer que le vecteur est désactivé dans toutes les circonstances. Sa durée de vie sera liée à l'objet/la fonction dans lequel vous êtes.
  3. nouveau/supprimer le vecteur. Cela libérera un peu plus de mémoire que la méthode précédente, mais il est aussi plus difficile de s'assurer qu'aucune mémoire ne fuit.

la seule différence technique entre l'échange et la suppression est que le vecteur de base lui-même est n'est pas détruit. C'est une petite surcharge et n'est pas la peine de s'inquiéter (tant que vous n'avez finalement détruire le vecteur)

la plus grande considération est ce qui rend plus facile d'écrire du code correct, et je pense que swap gagne sur la suppression là, mais est pire que de déplacer le vecteur ailleurs.

1
répondu Winston Ewert 2010-06-16 15:32:05

Supprimer désalloue la mémoire, la mémoire est alors libre pour le prochain objet, mais le vecteur a disparu.

2ème tour libère tout excès de mémoire, mais laisse le vecteur intacte, mais vide.

0
répondu Martin Beckett 2010-06-16 15:11:36

bien que les deux semblent fonctionner, Je ne vois aucune raison de ne pas simplement appeler supprimer sur le pointeur. Le vecteur doit avoir un destructeur est appelé qui va gérer tout le reste.

0
répondu Ben313 2010-06-16 15:12:24

si vous laissez le vecteur sortir du champ de vision, il se nettoiera de façon appropriée sans travail supplémentaire. Si le vecteur est une variable membre d'une classe, et que vous souhaitez libérer de son contenu avant son propriétaire, est détruite, puis il suffit d'appeler vec.clair.)(

Si vous voulez garder le vecteur mais désallouer la mémoire qui contient son contenu, puis vec.swap(std::vector<int>()); va le faire. Il n'est pas nécessaire de copier-construire le temporaire dans l'original à moins que vec contient des éléments que vous voulez gardez et vous voulez simplement rétrécir la mémoire allouée à quelque chose près de la taille actuelle().

0
répondu Alan 2010-06-16 15:18:59

ceci n'est pas une comparaison valable car les exemples traitent de différents types d'objets: la durée dynamique et la durée locale. Vous pouvez appeler le destructeur ou utiliser le truc de swap (alias shrink_to_fit) avec l'un ou l'autre. droit dépend si vous avez besoin de l'objet vectoriel de persistance ou non.

par exemple, vous pourriez en avoir besoin pour persister si il y a des références ou des pointeurs vers qui doit rester valable, auquel cas le rétrécissement est seule façon, indépendamment de la façon dont il a été affecté.

0
répondu Cubbi 2010-06-16 15:28:52

Je ne sais pas pourquoi votre second exemple utilise un constructeur de copie pour le constructeur temporaire plutôt qu'un constructeur par défaut. Que serait vous faire économiser de l' .clear() ligne de code.

vous pouvez le rendre générique pour n'importe quel objet, même s'il ne s'agit pas d'un conteneur. Je suppose ici que std::swap est spécialisé vecteur d'appel::swap.

template<typename T>
void ResetToDefault(T & value)
{
    std::swap(T(), value);
}

std::vector<int> vec;  
//...  
ResetToDefault(vec);
0
répondu Mark Ransom 2010-06-16 17:04:08

Dans le cas où le vecteur a vraiment besoin d'être sur le tas, n'oubliez pas:

std::auto_ptr<std::vector<int> > vec(new std::vector<int>);
std::auto_ptr<std::vector<int> > vec(vectorFactoryFunction());
0
répondu Graphics Noob 2010-06-17 18:16:20