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

Discussion :

Utilisation de push_front avec un QVector

  1. #1
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Décembre 2012
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Saône (Franche Comté)

    Informations forums :
    Inscription : Décembre 2012
    Messages : 5
    Points : 4
    Points
    4
    Par défaut Utilisation de push_front avec un QVector
    Bonjour,

    Depuis quelques jours, je débute avec Qt. Pour m'aider à apprendre, je m'amuse à créer des classes et à tester les résultats. Pour ce faire, j'ai créer une classe AnchorPoint.
    Dans le constructeur de cette classe, j'ai une variable m_Id qui me sert d'identificateur. m_Id est une variable statique qui est initiée à partir d'une autre variable statique que j'incrémente à chaque appel de nouvelle instance de ma classe.
    Jusqu'à là, rien d'extraordinaire.
    Dans mon Main, j'ai un QVector<AnchorPoint> et j'ajoute des AnchorPoint dans ce tableau...
    1) avec push_back puis je vérifie dans la sortie d’application à l'aide de qDebug(), la valeur de m_Id.
    Tout ce passe bien, pour chaque instance placée dans le QVector, il y a un m_Id qui s'incrémente.

    2) Même opération, mais cette fois avec push_front. Et là les instances ont des m_Id qui sont des multiples de 2 !
    J'ai l'impression qu'avec push_front, il y a création d'une nouvelle instance qui n'existe pas avec push_back.

    Bizarre. Si quelqu'un peut éclairer ma lanterne, j'en serais ravi. Par avance merci

  2. #2
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    696
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 696
    Points : 2 438
    Points
    2 438
    Par défaut
    Bonjour, bienvenue sur le forum

    Effectivement, l'objet doit être copié quelque part. Mais je doute que ça vienne de QVector,
    La doc dit que QVector::push_front() est un alias de QVector::prepend(), et les deux fonctions prennent ton objet soit en référence constante, soit "déplacent" l'objet (move semantic). Dans les deux cas, il n'y a pas de copie.

    Est-ce que tu peux nous montrer ton code ? Et tu utilises quelle version de Qt ?
    Je fais appel aux esprits de Ritchie, Kernighan, Stroustrup et Alexandrescu
    Donnez moi la force, donnez moi le courage de coder proprement !

    « Ça marche pas » n'est PAS une réponse convenable, merci de détailler le souci en fournissant l’environnement, le code source, les commandes et les messages d'erreur.

    Ce club possède également un clavardage, on y trouve quelques perles entre deux sessions d'entraides.

  3. #3
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Décembre 2012
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Saône (Franche Comté)

    Informations forums :
    Inscription : Décembre 2012
    Messages : 5
    Points : 4
    Points
    4
    Par défaut
    Bonjour Daïmanu et merci pour ton accueil
    Je suis sous Qt 5.14 et j'utilise le compilateur msvc2019 64 bit

    Le header ci dessous:
    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
    namespace GraphicPack
    {
    class AnchorPoint
        {
            //Variables Statiques
            int         m_Id {0};                               // Identificateur unique d'instance
     
        public:
            //Constructeurs
            AnchorPoint();
            AnchorPoint(qreal const x, qreal const y);
            AnchorPoint(qreal const x, qreal const y, qreal offsetX, qreal offsetY);
            AnchorPoint(QPointF const ptF,qreal offsetX, qreal offsetY);
            AnchorPoint(QPointF const ptF, QPointF const ptOffset);
            AnchorPoint(qreal const x, qreal const y, qreal radius);
            AnchorPoint(QPointF const ptF,qreal radius);
     
             //Destructeur
            ~AnchorPoint();
     
            //Ascesseurs
            int     Id() const;                                 // Retourne l'identificateur d'instance
     
      private:
           //Fonctions
            void    xDeclaration();                             // Défini les valeurs des différentes abscisses
            void    yDeclaration();                             // Défini les valeurs des différentes ordonnées
            void    constructorInit();                          // Lance l'initialisation des différents membres de la classe
    };
    Le CPP:

    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
    39
    40
    41
    42
    43
    using GraphicPack::AnchorPoint;
    //Constructeurs
    AnchorPoint::AnchorPoint()
    {
         m_Xinit = 0.0f;
         m_Yinit = 0.0f;
         constructorInit();
    }
     
    AnchorPoint::AnchorPoint(qreal const x, qreal const y)
    {
        m_Xinit = x;
        m_Yinit = y;
        constructorInit();
    }
     
    //Ascesseurs
    int  AnchorPoint::Id() const
    {
        return m_Id;
    }
     
    //Fonctions privées
    void AnchorPoint::constructorInit()
    {
        static int counter=1;
        m_Id = counter ++;
        m_Xin = m_Xinit;
        m_Yin = m_Yinit;
        //Défini Xout et Yout
        xDeclaration();
        yDeclaration();
    }
     
    void AnchorPoint::xDeclaration()
    {
        if(m_RandomActived != true) m_Xout = m_Xin + m_OffsetX;
    }
     
    void AnchorPoint::yDeclaration()
    {
          if(m_RandomActived != true)  m_Yout = m_Yin + m_OffsetY;
    }
    J'ai réduit mon code car il y a plusieurs membres et fonctions qui s'en reporte mais qui n'utilisent pas m_Id.

    Mon Main
    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
     using GraphicPack::AnchorPoint;
        QVector<AnchorPoint> ListOfAnchorPoint;
        AnchorPoint pt0 (100,190);
     
        qDebug()<< "pt0.id = " << pt0.Id() ;
     
        ListOfAnchorPoint.push_front(pt0);
     
        qDebug()<< "ListOfAnchorPoint[0].id = " << ListOfAnchorPoint[0].Id() ;
     
        AnchorPoint pt1 (120,50);
     
        qDebug()<< "pt1.id = " << pt1.Id() ;
     
        ListOfAnchorPoint.push_front(pt1);
        qDebug()<< "ListOfAnchorPoint[1].id = " << ListOfAnchorPoint[0].Id() ;
     
        AnchorPoint pt2 (312,55);
        qDebug()<< "pt2.id = " << pt2.Id() <<"\n";
     
        ListOfAnchorPoint.push_front(pt2);
        qDebug()<< "ListOfAnchorPoint[2].id = " << ListOfAnchorPoint[0].Id() <<"\n";
     
        AnchorPoint unPoint (60,55);
        qDebug()<< "unPoint.id = " << unPoint.Id() <<"\n";
     
        AnchorPoint deuxPoint(10,31);
        qDebug()<< "deuxPoint.id = " << deuxPoint.Id() <<"\n";
     
        AnchorPoint EtDeTrois(0.0f,0.0f);
        qDebug()<< "EtDeTrois.id = " << EtDeTrois.Id() <<"\n";
    Le résultat avec push_front
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    18:59:29: Debugging starts
    pt0.id =  1
    ListOfAnchorPoint[0].id =  1
    pt1.id =  3
    ListOfAnchorPoint[1].id =  3
    pt2.id =  5 
     
    ListOfAnchorPoint[2].id =  5 
     
    unPoint.id =  7 
     
    deuxPoint.id =  8 
     
    EtDeTrois.id =  9
    Et le résultat avec push_back (en modifiant bien entendu les indices du vector...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    19:02:15: Debugging starts
    pt0.id =  1
    ListOfAnchorPoint[0].id =  1
    pt1.id =  2
    ListOfAnchorPoint[1].id =  2
    pt2.id =  3 
     
    ListOfAnchorPoint[2].id =  3 
     
    unPoint.id =  4 
     
    deuxPoint.id =  5 
     
    EtDeTrois.id =  6
    QVector si j'ai bien compris fais une copie "const"de mon point lorsque je l'ajoute. Comme j'utilise le constructeur de copie implicite, j'ai en créé un pour vérifier qu'il n'y avait pas de liaison avec mon m_Id. Rien à ce niveau !

    En plaçant un point d'arrêt dans mon constructeur, il y a bien 9 appels à ce dernier avec push_front et seulement 6 avec push_back.

    Où est mon erreur ? Qu'ai je pas compris ?

    Par avance merci

  4. #4
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Bonjour,

    Ce qu'il faut savoir c'est qu'un vector met ses données dans une zone de mémoire qu'il a réservé.
    Quand on veut ajouter un objet:
    - s'il y a assez de place dans la zone pour un élément de plus:
    ---- si c'est en fin, l'objet est directement copié en fin.
    ---- si c'est ailleurs (en particulier au début), il copie chacun des éléments à partir de la position d'insertion dans leur case suivante, et finit en copiant l'objet à la position désirée.
    - si la zone mémoire est à son maximum: il reserve un nouvelle zone plus grande, copie tous les éléments dans cette nouvelle zone à leur nouvelle position, l'objet est directement copié à la bonne position, puis il détruit tous les éléments dans l'ancienne zone.

    Qu'entend-on ici par "copie"?
    - si on copie dans un emplacement où il y avait déjà un objet, c'est l'opérateur de copie ou de transfert qui est utilisé.
    - si on copie dans un emplacement vierge, c'est le constructeur de copie ou de transfert qui est utilisé.

    Donc ça devrait fonctionner.
    Mais il existe aussi une autre manière de copier, et il semblerait que Qt utilise celle là:
    - On peut créer un objet par défaut (donc qui ferait l'incrémentation) et utiliser l'opérateur de copie ou de transfert pour le mettre à jour.
    Cette dernière méthode n'a de sens que si le constructeur de copie est inaccessible, ça ne semble pas le cas ici.

    Essaie d'enlever le constructeur par défaut, il est alors possible que ça ne compile plus ou bien que le défaut se déplace.

  5. #5
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Décembre 2012
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Saône (Franche Comté)

    Informations forums :
    Inscription : Décembre 2012
    Messages : 5
    Points : 4
    Points
    4
    Par défaut
    Bonjour dalfab,

    Merci pour ces explications très claires. Effectivement lorsque je supprime le constructeur par défaut, j'ai le message d'erreur suivant à la compilation:

    "Aucun constructeur par défaut disponible pendant la compilation membre classe modèle *QVector<AnchorPoint>::insert (Anchor<point, *int,const T&)"

    J'ai une explication claire sur ce qui ce passe.

    Maintenant, il me reste à prendre une décision sur le choix de continuer à avoir un identificateur pour chaque instance de ma classe.
    J'avais dans l'idée de m'en servir pour gérer une liaison entre points de type "Maître-Esclave" en créant une classe MovableAnchorPoint dérivée de QObject.
    Ceci pour avoir la possibilité d'émettre un signal lors du déplacement du point "Maître" vers le ou les points "Esclave" qui se déplaceraient du même vecteur (au sens mathématique).

    Maintenant, au pire, si on utilise avec push_front (qui n'est pas une obligation), j’aurais des "manques" dans les identificateurs.
    Ce qui, me semble t-il, n'a pas de répercutions sur le fonctionnement que je veux en faire. Juste un problème de logique intellectuelle qui est à l'origine de ce post.

    Une fois encore, merci à tous les deux d'avoir consacré un peu de votre temps sur mes questionnements. C'est sympa

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

Discussions similaires

  1. Utiliser DirectX 9 avec C++Builder
    Par Olivier Constans dans le forum DirectX
    Réponses: 2
    Dernier message: 27/06/2005, 11h30
  2. utilisation de dll avec diverses compilateurs
    Par Thylia dans le forum C++
    Réponses: 30
    Dernier message: 21/10/2004, 16h30
  3. Problème d'utilisation de Mysql avec dev-c++
    Par Watchi dans le forum Dev-C++
    Réponses: 10
    Dernier message: 06/08/2004, 14h35
  4. utilisation de fetch avec select
    Par arwen dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 06/06/2003, 10h03
  5. Utiliser Borland C++ avec Emacs sous Windows
    Par Eikichi dans le forum Autres éditeurs
    Réponses: 2
    Dernier message: 02/03/2003, 08h40

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