IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SL & STL C++ Discussion :

List et Vector : mise au point


Sujet :

SL & STL C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Par défaut List et Vector : mise au point
    Bonsoir,

    Je travaille actuellement sur un petit projet où je fais des requête sql à l'aide de QSql et à l'aide de quelques fonctions je crée une liste de message.

    Pour l'instant c'est très lourd, mais je compte bien faire différemment.

    J'utilisais les vector mais le fait de parcourir mon vector et de faire des push_back, invalidait l'iterator.

    Du coup, je suis passé au liste. Et là plus de problème. Je me demande tout de même si ce n'est pas un peu sale.

    Voici :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    void Feeder::update()
    {
            std::wstring tempString;
            queryExec("SELECT * FROM staff WHERE salary > 1000");
     
            std::list<SimpleMessage*>::iterator it = m_messageList.begin();
     
     
            while (queryNext()) 
            {
               tempString = (getValue(1).toString()).toStdWString () ;
     
                if( it != m_messageList.end() )
                {
                    if(*it)
                    {   
                        if( (*it)->getContent() == tempString )
                        {
                            ++it;
                        }
                        else 
                        {   
                            m_messageList.push_back( new SimpleMessage( (getValue(1).toString()).toStdWString ()) );  
                        }
                    }
                    else
                    {
                        cout<<"error  NULL pointer on MessageList... "<<endl;
                    }
                }
                else
                {
                    m_messageList.push_back( new SimpleMessage( (getValue(1).toString()).toStdWString ()) );
                    it = m_messageList.begin();
                }
            }
    }
    Merci d'avance !

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Je ne suis pas sur d'avoir tout compris à ce que tu voulais faire et en particulier pourquoi tu veux maintenir un itérateur sur ton conteneur. Cet itérateur varie assez étrangement dans ton code - dont je n'ai pas tout saisi.
    Donc, je vais dire 2 ou 3 bêtises en espérant qu'elles ne tombent pas trop à côté :
    1/ Si tu veux des chaînes distinctes, et bien précises le dans ta requête SQL plutôt que dans le traitement C++. Ce sera sans contexte + efficace.
    2/ Si tu veux utiliser un vector, tu peux faire une première fois un SELECT COUNT(*) FROM staff WHERE salary > 1000, puis un reserve pour éviter les réallocation permanente. Attention reserve ne créé pas d'éléments mais permet de réallouer le tableau interne. Si la liste était vide, elle reste vide.
    3/Tu peux utiliser un indice (valide) pour accéder à tes éléments et l'opérateur [] sur ton vecteur.
    4/ Pourquoi avoir un conteneur de pointeur (SimpleMessage*) et pas directement d'éléments (SimpleMessage)?

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Par défaut
    Alors :

    1. Je n'ai pas compris la première question.

    2. je n'ai pas vraiment compris la réponse du point deux.

    3. pour l'histoire de l'indice, je compte faire cela pour la suite. J'enregistre où est-ce que je me trouvais la dernière fois que j'ajoutais un message et je n'ajoute que si l'indice suivant contient des informations.

    Mais pour le moment je souhaite comprendre, la manière compliqué qui fut mon premier jet.

    4. hum, je fais comment pour créer dynamiquement mes objets messages qui seront effacés, ajoutés comme cela au bon vouloir des moments où ils arrivent dans la BDD ?

    Merci de cette réponse rapide !

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    1/ Peux-tu expliquer ce qu'est supposé faire ta fonction ? Je ne comprend pas pourquoi tu fais le test if( (*it)->getContent() == tempString ) et comment évolue ton itérateur. Est-ce pour ne pas insérer une chaîne déjà existante ?
    2/ Si tu utilises un vecteur et que tu rajoutes beaucoup d'éléments, il est plus performant de faire d'abord un mon_vecteur.reserve(nb_element), puis des mon_vect.push_back. D'où l'idée de faire une première requête pour compter les éléments et réserver, puis une seconde pour récupérer les éléments.
    4/ Je ne vois pas le rapport. Tu peux très bien ajouter ou enlever des éléments d'un conteneurs. Maintenant, si tu dois être amené à faire beaucoup d'opération d'ajout/suppression alors reste sur une std::list. Ce sera + performant qu'un std::vector.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    1/ Peux-tu expliquer ce qu'est supposé faire ta fonction ? Je ne comprend pas pourquoi tu fais le test if( (*it)->getContent() == tempString ) et comment évolue ton itérateur. Est-ce pour ne pas insérer une chaîne déjà existante ?
    Exactement (ce qui n'est pas très malin)

    Citation Envoyé par 3DArchi Voir le message
    2/ Si tu utilises un vecteur et que tu rajoutes beaucoup d'éléments, il est plus performant de faire d'abord un mon_vecteur.reserve(nb_element), puis des mon_vect.push_back. D'où l'idée de faire une première requête pour compter les éléments et réserver, puis une seconde pour récupérer les éléments.
    Ok, je ne savais pas... Je vais faire cela

    Citation Envoyé par 3DArchi Voir le message
    4/ Je ne vois pas le rapport. Tu peux très bien ajouter ou enlever des éléments d'un conteneurs. Maintenant, si tu dois être amené à faire beaucoup d'opération d'ajout/suppression alors reste sur une std::list. Ce sera + performant qu'un std::vector.
    Je m'imaginais que cela était moin "couteux" puisque si je fais un vector<SimpleMessage>, et non vector<SimpleMessage*>, il va créer une copie et après chaque push_back le SimpleMessage orignal sera supprimé.

    Même si le résultat final (j'ai bien accès à mes SimpleMessage dans la liste ou le vector) est le même, les opérations effectuées sont différentes.

    C'est la constatation que je fais, si je fais des "output" à l'appel du destructeur d'objet SimpleMessage :

    Dans le cas de vector<SimpleMessage>, l'appelle des destructeurs à lieu après chaque pushback alors qu'avec un vector<SimpleMessage*>, l'appel du destructeur n'a lieu que lorsque je quitte le programme.


    Merci encore !

  6. #6
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Bonjour,

    J'utilisais les vector mais le fait de parcourir mon vector et de faire des push_back, invalidait l'iterator.
    Dans ce genre de cas, on peux s'en sortir en convertissant en offset, puis en repassant en itérateur après l'opération d'insertion.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    if( (*it)->getContent() == tempString )
    {
       ++it;
    }
    else 
    {  
       std::vector<int>::difference_type offset = std::distance(m_messageList.begin(), it);
       m_messageList.push_back( new SimpleMessage( (getValue(1).toString()).toStdWString ()) );
       it = m_messageList.begin();
       std::advance(it, offset);           
    }
    Ceci dit, j'ai les mêmes réserves que 3DArchi sur ton code. La logique a l'air un peu bizarre et je n'arrive pas à traduire en mot ce que le code fait.

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Par défaut
    Alors c'est très simple !

    Je viens intéroger la base de donnée,

    Je regarde si la liste à un élément,

    sinon j'ajoute le premier élément.

    Je regarde le champs de la table qui m'intéresse, et je compare le champs au contenu du message.

    Si le champs en question est présent dans le message je passe mon chemin.
    Sinon j'ajoute un message à la liste de message avec le nouveau contenu du champs.

    Ainsi, j'ajoute des SimpleMessages à chaque nouveau champs rempli dans la table concernée.

    Je parcours à chaque appel de la fonction update tous les champs de table et les compare à la liste courante. Oui c'est long et stupide mais je n'avais pas pensé à mettre un flag pour voir s'il y a du nouveau ou encore utilisé les idée de chaque ligne de ma table pour maintenir à jour ma liste de SimpleMessage.

    Comme j'étais sur un bug que je ne comprenais pas (avec l'utilisation de vector) et que j'ai résolu par un changement en list, je préférais poser la question.

    Merci

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Je maintiens ne pas bien comprendre...
    Pour le 1er élément, sors le de ta boucle, ça t'évitera de faire le test à chaque itération.
    Pour ce qui est de comparer par rapport au champs : tu peux déjà demander des DISTINCT dans ta requête SQL ou rajouter des WHERE XXXX NOT IN ou quelque chose de ce genre (voire les spécialistes de SQL) pour permettre à SQL de ne te retourner que les valeurs qui t'intéresse.

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Je maintiens ne pas bien comprendre...
    Pour le 1er élément, sors le de ta boucle, ça t'évitera de faire le test à chaque itération.
    Pour ce qui est de comparer par rapport au champs : tu peux déjà demander des DISTINCT dans ta requête SQL ou rajouter des WHERE XXXX NOT IN ou quelque chose de ce genre (voire les spécialistes de SQL) pour permettre à SQL de ne te retourner que les valeurs qui t'intéresse.
    Je ne connais rien à SQL. Ce que tu dis là m'intéresse ! Mais pour le moment restons-en au list et vector. En fait, je me demande pour quelle raison, un push_back sur un vector invalide l'iterator alors que sur une liste au premier abord pas de problème....

  10. #10
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    lorsque tu insère un élément dans un vector, il peut avoir besoin ^'être entièrement réalloué par manque de place. De ce fait, le début du vector ne sera plus le même. Sur une liste, il n'y a pas de réallocation, il y a juste un nouveau maillon qui est ajouté dans la liste ce qui ne change pas (trop) les iterator.

    Un petit coup d'oeil ici pour comprendre un peu plus (j'ai pas trouvé en français)
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Convertir List en Vector
    Par michaelbob dans le forum Collection et Stream
    Réponses: 12
    Dernier message: 10/05/2011, 16h25
  2. Mise au point d'un bon algo
    Par cryptorchild dans le forum Langage
    Réponses: 3
    Dernier message: 08/10/2005, 17h04
  3. Petite mise au point avec gluUnProject.
    Par fatpat94 dans le forum OpenGL
    Réponses: 1
    Dernier message: 27/07/2005, 15h40
  4. [Mise au point] dhcp
    Par Ernest dans le forum Développement
    Réponses: 5
    Dernier message: 07/10/2004, 17h56
  5. Questions de mise aux points
    Par nicoo dans le forum DirectX
    Réponses: 5
    Dernier message: 11/05/2004, 14h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo