Comment définir la taille initiale de std :: vector?

130

J'ai un vector<CustomClass*>et j'ai mis beaucoup d'éléments dans le vecteur et j'ai besoin d'un accès rapide, donc je n'utilise pas de liste. Comment définir la taille initiale du vecteur (par exemple 20 000 places, donc pour éviter la copie lorsque j'en insère un nouveau)?

Damir
la source
1
Il y a un constructeur et deux fonctions pour cela dans n'importe quelle std::vectorréférence, en fonction de ce qui correspond le mieux à vos besoins.
chris
1
Vous ne pouvez pas éviter de copier simplement en définissant la valeur initiale.
juanchopanza
1
Évitez les copies de? Le stockage des pointeurs est assez léger en termes de coût de copie.
user7116
1
@Damir, vouliez-vous dire std::vectordans le titre?
Robᵩ

Réponses:

180
std::vector<CustomClass *> whatever(20000);

ou:

std::vector<CustomClass *> whatever;
whatever.reserve(20000);

Le premier définit la taille réelle du tableau, c'est-à-dire en fait un vecteur de 20000 pointeurs. Ce dernier laisse le vecteur vide, mais réserve de l'espace pour 20000 pointeurs, vous pouvez donc en insérer (jusqu'à) autant sans qu'il soit nécessaire de le réallouer.

Au moins d'après mon expérience, il est assez inhabituel que l'un ou l'autre de ces éléments fasse une énorme différence en termes de performances - mais l'un ou l'autre peut affecter l'exactitude dans certaines circonstances. En particulier, tant qu'aucune réallocation n'a lieu, les itérateurs dans le vecteur sont garantis pour rester valides, et une fois que vous avez défini la taille / l'espace réservé, vous êtes assuré qu'il n'y aura pas de réallocations tant que vous ne le faites pas. t augmenter la taille au-delà.

Jerry Coffin
la source
Lequel de ceux-ci serait le plus efficace pour un grand nombre d'insertions / suppressions?
ctor le
3
@Loggie: Je doute qu'il y ait une différence d'efficacité. La plupart du temps, cela change la façon dont vous l'utilisez - avec le premier, vous vous contentez d'adresser les pointeurs, donc quelque chose comme whatever[10000] = somepointer;, où le dernier vous oblige à push_backchaque pointeur que vous ajoutez. Au moins si vous y êtes habitué vector, ce dernier est probablement plus simple et plus naturel.
Jerry Coffin
Si la taille du conteneur copié est connue, pourquoi n'est-il pas plus efficace de (re) redimensionner puis de copier au lieu de pushing_back?
1
@Cincinnatus: Parce qu'il a un appel à reserve, qui pré-alloue la taille de la mémoire. En théorie, la définition de la taille pourrait encore être minutieusement plus rapide, car elle évite également d'incrémenter la taille actuelle à chaque fois que vous ajoutez un élément. En réalité, je doute que vous puissiez mesurer cela.
Jerry Coffin
1
en fait, si vous faites cela sur un chemin actif et que le code est beaucoup appelé, vous pouvez faire beaucoup d'instructions et gagner du temps.
bayindirh
15

Vous devez utiliser la fonction reserve pour définir une taille allouée initiale ou le faire dans le constructeur initial.

vector<CustomClass *> content(20000);

ou

vector<CustomClass *> content;
...
content.reserve(20000);

Lorsque vous reserve()éléments, vous vectorallouerez suffisamment d'espace pour (au moins?) Autant d'éléments. Les éléments n'existent pas dans le vector, mais la mémoire est prête à être utilisée. Cela va alors éventuellement s'accélérer push_back()car la mémoire est déjà allouée.


la source
L'allocation de la taille peut également être fournie lors de la construction en passant un argument intégral (par exemple std::vector<Custom Class*> content(100);)
adelbertc
@kstruct: Oui, mais cela peut être moins efficace - par une très petite quantité.