3
votes

Comment vector :: size () renvoie la taille du vecteur en temps constant?

J'étais en train de parcourir cette Référence C ++ et j'ai constaté que l'utilisation de vector :: size () renvoie la taille du vecteur en temps constant. Mais, je me demande comment on pourrait obtenir la taille sans réellement traverser le vecteur.


4 commentaires

comment obtiendriez-vous la taille en parcourant le vecteur? vous devez connaître la taille pour savoir où arrêter de parcourir


Question potentiellement pertinente: C ++ sizeof Vector est 24? .


La taille est stockée dans une variable membre.


@Shawn Pas nécessairement.


3 Réponses :


9
votes

Il ne fait que suivre le nombre d'éléments.

Si cela change, ce numéro est mis à jour. Par exemple, le nombre d'éléments augmente de 1 lorsque push_back ou emplace_back est appelé. C'est l'une des nombreuses raisons pour lesquelles std :: vector n'est pas intrinsèquement thread-safe.

Comme vous pouvez l'imaginer, cela rend l'implémentation de std :: vector assez fastidieuse - la même chose peut être dite pour d'autres conteneurs de bibliothèques standard C ++ également - ce qui est une bonne raison pour ne pas essayer d'écrire classes de conteneurs vous-même.


4 commentaires

Pourquoi avons-nous besoin de garder une autre variable pour le nombre d'éléments si nous pouvons obtenir directement le nombre d'éléments simplement en divisant la capacité du vecteur par la taille du premier élément?


Je n'ai pas dit cela - je suis un chat prudent vous savez!


La capacité et la taille de @HimanshuKumar sont des choses différentes pour std :: vector . Vous ne voulez pas augmenter la capacité à chaque fois que vous ajoutez un élément (car cela implique de réallouer le tableau interne et de copier / déplacer tous les éléments), donc vous augmentez la capacité de gros morceaux (généralement de façon exponentielle) même si vous n'êtes qu'un élément trop court.


@HimanshuKumar taille et capacité sont deux choses différentes, où taille <= capacité . La capacité est le nombre maximum d'éléments que la mémoire actuellement allouée peut contenir au total. La taille est le nombre d'éléments réels qui sont valides dans la mémoire actuellement allouée. La mémoire est réallouée lors des insertions lorsque la nouvelle taille dépasserait la capacité actuelle.



8
votes

Pour comprendre cela, vous devez comprendre comment fonctionne le vecteur.

Un bon modèle mental est:

T& push_back(T const& t)
 {
      if (size == capacity)
            grow();
       constructAtEnd(t);
       ++ size;
        return back();
  }

Chaque fois qu'un élément est ajouté:

  • L'élément est construit
  • la taille est incrémentée
  • Lorsqu'il n'y a pas assez de capacité, nous devons augmenter les données. Bref, si vous regardez le code de push_back, il ressemblera à:

    class vector
    {
          T *data;.              // Pointer to the first element
          size_t size;         // Number of elements in use
          size_t capacity; // Number of elements available
    };
    

    En pratique, c'est un peu plus complexe à cause des garanties d'exception. Cependant, compte tenu de ce qui précède, vous devriez être en mesure de vérifier votre implémentation de vector et de reconnaître ce qui se passe, pour toutes les méthodes.


    9 commentaires

    "La plupart des implémentations" stockent données + taille et données + capacité au lieu de la taille et de la capacité (cela n'affecte cependant pas le modèle mental).


    @MarcGlisse: Peut-être, mais notez que tous doivent utiliser std :: vector <> :: size_type comme type pour le nombre d'éléments. Ce n'était pas l'intention du répondant d'aller aussi loin; Je suis sûr. Ayez un vote positif!


    @Marc MSVC ne le fait certainement pas. Libc ++ fait quelque chose de similaire basé sur 3 pointeurs


    Les traits @Marc Type rendent en effet les choses plus complexes, j'ai tendance à les ignorer si vous n'utilisez pas d'allocateurs personnalisés


    Personnellement, je laisserais tomber "(la plupart des implémentations l'implémentent même de cette façon)" - cela ruine la réponse.


    Il devrait être if (size> = capacity) grow ();


    @chtz Si size> capacité vous avez déjà foiré, alors size == capacity est le seul cas pertinent.


    @MaxLanghof, oui == c'est bien aussi. Avant mon commentaire, il était dit size + 1> = capacité qui augmenterait prématurément.


    @chtz Apologies, vérifiera l'historique des modifications la prochaine fois.



    0
    votes

    std :: vector est un conteneur de séquence dans la STL et il a une variable avec le nombre d'éléments à chaque fois. Lorsque nous push_back () n'importe quel élément du std :: vector cette variable s'incrémente et lorsque nous pop_back () élément du std :: vector cette variable décrémente.

    Donc je pense que ça marche comme ça

    Donc std :: vector :: size () renvoie la taille de cette variable


    0 commentaires