2010-10-31 29 views
1

J'ai du mal à obtenir la bonne taille d'un vecteur avec des éléments struct. La classe d'élément est défini comme celui-ci (je n'omets aucun détail, même si je pense que le seul fait pertinent est qu'il est une classe contenant un entier et deux doubles):taille de std :: vector avec struct elements

class Interval 
{ 
public: 
    Interval(int _i = 0, scalar _l = 0, scalar _r = 0) : 
     index(_i), 
     l(_l), 
     r(_r) 
    { } 

    inline double left(void) const { return l; } 
    inline double right(void) const { return r; } 

    inline bool operator < (const Interval & i2) const { return left() < i2.left(); } 

public: 
    int index; 
    double l; 
    double r; 

}; 

Puis, en fonction je ce code:

std::vector<Interval> arr(10); 
int s1 = arr.size(); 
int s2 = arr.end() - arr.begin(); 

la valeur de s1 je reçois est de 15, alors que s2 est la valeur correcte 10. Que se passe-t-il? Est-ce que size() n'est pas supposé retourner exactement le nombre d'éléments? N'est-ce pas censé être le même que arr.end() - arr.begin()?

Toute réponse et commentaire est apprécié.

+0

Il n'y a aucune manière connue qu'une exécution fonctionnante de vecteur le fera. Veuillez montrer tout le code que vous utilisez pour le vérifier. –

+0

Oui, size() est supposé égal à end() - begin(); nous avons besoin d'un meilleur test pour comprendre ce qui se passe. –

+0

Ne sois pas vague, sois un as; apprendre à écrire un test-case approprié! http://sscce.org/ http://www.xs4all.nl/~weegen/eelis/iso-c++/testcase.xhtml http://tinyurl.com/so-hints –

Répondre

0

Modifier: Maintenant que vous avez fourni plus d'informations, nous pouvons peut-être faire la lumière sur ce comportement déroutant.

Vous avez enfreint le One Definition Rule. Les résultats de cela ne sont pas vraiment définis, mais nous pouvons faire quelques suppositions éclairées basées sur vos résultats observés.

Les fonctions de modèle sont toujours déclarées en ligne, car elles sont requises pour la substitution de paramètres de modèle. Lorsque le compilateur rencontre l'une de ces fonctions, il a le choix de l'émettre comme code en ligne ou de créer un corps de fonction et de l'appeler. S'il crée un corps de fonction, le lieur devient responsable de l'élimination des définitions en double dans différentes unités de traduction. L'éditeur de liens ne fait pas beaucoup de vérifications pour voir si les doublons apparents sont fonctionnellement équivalents, il passe juste par le nom décoré de la fonction, qui dépend des types d'arguments; Si les types ont tous le même nom, ils sont supposés identiques. Il peut faire cette hypothèse en raison de la règle de définition unique.

Voici comment vous pouvez faire en sorte qu'une définition de classe qui n'est pas incluse dans votre source affecte le résultat de votre code - l'éditeur de liens substitue une mauvaise copie du code pour une bonne. Si le compilateur génère un code en ligne, vous obtiendrez les résultats escomptés. Si l'éditeur de liens est impliqué, vous avez 50% de chances de vous tromper. Et même si votre code a de la chance, un autre morceau de code est maintenant battu.


Réponse originale: Il est possible qu'un vecteur soit plus grand que la taille demandée, mais size ne reflétera pas cette valeur; vous pouvez tester cela en utilisant capacity. L'espace de stockage excédentaire fera partie de l'utilisation de la mémoire, mais les éléments ne seront pas initialisés et toute tentative d'accès au-delà du résultat de size entraînera un comportement indéfini.

+0

Merci, je comprends la différence entre la capacité et la taille. J'ai des problèmes avec la taille en particulier. – fang

+0

Merci beaucoup. C'est clair pour moi maintenant. – fang

+0

J'ai du mal à voir comment le code de l'OP viole l'ODR, ou comment cette réponse résout le problème. –

1

Arrêtez tout d'abord d'utiliser des balises HTML lors du formatage du code. Utilisez le bouton [Code] à la place. Deuxièmement, ce que vous décrivez est un mystère qui défie toute explication. Vous devriez obtenir la même valeur - 10 - dans les deux s1 et s2. C'est à moins que vous n'ayez réussi à détruire l'intégrité de votre vecteur dans un autre code (c'est-à-dire que le code que vous exécutez n'est pas le code que vous nous montrez).

+0

Merci pour le conseil. Je vais essayer de le faire la bonne fois la prochaine fois. – fang

+0

Je sais ce que j'ai montré n'a aucun sens. Ce que je demande, c'est essentiellement un aperçu de ce qui peut être peut-être gâcher les choses. La seconde moitié du code affiché initialise un vecteur et demande immédiatement la taille, donc il n'y a pas beaucoup de possibilités, je ne peux pas y penser. J'ai besoin de votre expérience d'experts pour connaître le bon endroit pour regarder (comme, avez-vous déjà vu des problèmes similaires avec d'autres personnes, quelles étaient les réponses, etc.). Je suis sûr que la réponse finale à celui-ci est probablement stupide, mais je suis coincé sur moi-même. – fang

1

fonctionne comme prévu dans Codepad

+0

Merci pour la vérification. Je l'ai fait aussi, et comme prévu, le problème n'est pas dans la partie du code que j'ai montré. Comme je l'ai dit dans le dernier commentaire, je cherche des réponses comme le type de mécanisme en C++ qui pourrait permettre à d'autres codes d'interférer avec le code aussi simple que ceux que j'ai montrés, parce que je n'y pense pas. – fang

0

Mise à jour: Après avoir exploré le code de base dans le projet, je trouve une autre classe avec le même nom « Intervalle » dans une autre tête écrit par d'autres personnes (mon mauvais d'avoir choisi un si simple mot que mon nom de classe).Cette classe contient deux doubles (16 octets sur ma machine, alors que ma classe a 24 octets), ce qui explique apparemment pourquoi l'appel de size() renvoie 50% de plus que le nombre réel d'éléments.

Mais je ne comprends pas comment std :: vector pourrait être confondu par les deux définitions (je n'ai pas inclus cet en-tête dans mon code, mais mes en-têtes sont probablement inclus dans d'autres parties du projet après inclusion de header), et comment end() - begin() utilise une définition tandis que size() utilise une autre définition. Btw, pour éviter de telles collisions dans un projet multi-programmeur, la meilleure pratique serait d'utiliser des espaces de noms, n'est-ce pas? Merci.

+0

Merci pour cette information supplémentaire, j'ai mis à jour ma réponse. –

+0

Moot point maintenant, mais vous auriez pu modifier votre question. –

+0

@Marcelo, à droite, merci pour le conseil. J'ai vu quelques personnes poster des mises à jour en répondant à leurs propres questions auparavant, alors j'ai pensé que c'était une façon courante de le faire. Je n'ai jamais réalisé que j'aurais pu éditer un article original. – fang