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

Qt Discussion :

Petite question mécanique sur la suppression de QObject


Sujet :

Qt

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Par défaut Petite question mécanique sur la suppression de QObject
    Hello,

    J'ai pu lire ça dans la faq:
    http://qt.developpez.com/faq/?page=Q...qobject-membre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class monObj : QObject
    {
    QTimer m_timer;
    public :
        monObj ()
        {
            m_timer.setParent(this);
        }
    }
    "Il est très important que tous les QObject en membre d'une classe ait pour parent this."


    Ce qui me fait bizarre et que je ne comprends pas trop bien. Sauf erreur dans l'exemple ci dessus. L'ordre de destruction devrait être :

    1) destructeur de monObj
    2) destructeur de m_timer
    3) destructeur de QObject

    Si cela est bien correct, c'est le destructeur de QObject qui va détruire les enfants, donc entre autre m_timer mais ce dernier est déjà liquidé à ce moment-là.

    Selon mon interprétation de la doc, la destruction de m_timer a pour effet de le retirer de la liste des enfants de monObj, c'est pour cela en fait que je pense que ça ne fait pas d'erreur si m_timer n'existe plus au moment ou le destructeur de QObject fait le nettoyage.

    Ca me paraît confus, mais si mon analyse est correcte (ce qui reste à déterminer), on ne devrait pas appeler setParent(this) sur un QObject membre non pointeur.

    Vous pouvez m'aidez à comprendre?

  2. #2
    Membre émérite

    Profil pro
    Inscrit en
    Mai 2007
    Messages
    774
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mai 2007
    Messages : 774
    Par défaut
    Selon mon interprétation de la doc, la destruction de m_timer a pour effet de le retirer de la liste des enfants de monObj, c'est pour cela en fait que je pense que ça ne fait pas d'erreur si m_timer n'existe plus au moment ou le destructeur de QObject fait le nettoyage.

    Ca me paraît confus, mais si mon analyse est correcte (ce qui reste à déterminer), on ne devrait pas appeler setParent(this) sur un QObject membre non pointeur.

    Vous pouvez m'aidez à comprendre?
    Ton interprétation de la doc est la même que moi. Donc en effet, je ne pense pas qu'il soit nécessaire de faire un setParent pour une variable allouée "statiquement" (j'entends par là non pointeur). Après, je crois que pour les QWidgets, cela a une importance (notamment en ce qui concerne les layouts des fenêtres), et au pire il n'y a pas d'inconvénients à le faire.

    G.

  3. #3
    Membre éprouvé
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Par défaut
    En fait, dans les exemples de Qt il me semble qu'ils stockent toujours des pointeurs vers les QObject, et là effectivement ils donnent directement "this" au constructeur lorsque le membre est alloué.
    Comme ça le destructeur du parent liquide le QObject créé sans code additionnel dans la classe courante.

    En fait, il semble plutôt que tous les membres qui ne font pas du comptage de référence (donc hors QString, QList etc..) devraient être des pointeurs sauf cas particulier.

  4. #4
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Salut

    Citation Envoyé par _skip Voir le message
    1) destructeur de monObj
    2) destructeur de m_timer
    3) destructeur de QObject
    C'est du C++ donc les membres sont détruit avant
    1) destructeur de m_timer
    2) destructeur de monObj
    3) destructeur de QObject

    Après, je crois que pour les QWidgets, cela a une importance (notamment en ce qui concerne les layouts des fenêtres), et au pire il n'y a pas d'inconvénients à le faire.
    Pareil c'est une règle du C++ :
    les membres sont créés dans l'ordre de leurs déclaration et détruit dans l'ordre inverse.
    Donc avec la gestion de parent/enfant, il peut y avoir des problèmes. Utiliser un pointeur enlève ce problème.

    En fait, il semble plutôt que tous les membres qui ne font pas du comptage de référence (donc hors QString, QList etc..) devraient être des pointeurs sauf cas particulier.
    Surtout pas. Il n'y as pratiquement aucun intérêt à faire cela. A part ajouter de la complexité en devant gérer leur destruction. En plus ils utilisent le COW.

    Pourquoi faut il mettre un parent? Par ce que certain traitements qui s'applique sur un QObject va s'appliquer ou on besoin de ce lien parent/enfant sur ses QObject enfants :
    - moveToThread
    - les recherche de QObject enfants
    - ...

    Après, c'est recommandé. Pas obligatoire. Surtout dans un environnement multi-thread.
    [edit]
    Remarque, peut être qu'utiliser un pointeur est plus simple à comprendre.


    Peut être faut il clarifier la QR.

  5. #5
    Membre éprouvé
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Par défaut
    Si ça t'embête pas qu'on discute de ça, c'est intéressant, tout cas pour moi.

    Citation Envoyé par yan Voir le message

    C'est du C++ donc les membres sont détruit avant
    1) destructeur de m_timer
    2) destructeur de monObj
    3) destructeur de QObject


    Pareil c'est une règle du C++ :
    les membres sont créés dans l'ordre de leurs déclaration et détruit dans l'ordre inverse.
    Alors t'es sûr de ça? Parce que selon mes connaissances (plus limitées que les tiennes sans doute je l'admet) c'est l'ordre inverse de complétion des constructeurs qui joue et non pas l'ordre d'invocation.

    D'ailleurs pour cause, dans le destructeur de monObj, tu es libre d'accéder aux propriétés des objets membres (ici m_timer), ce qui devrait signifier qu'il n'est pas liquidé.


    Surtout pas. Il n'y as pratiquement aucun intérêt à faire cela. A part ajouter de la complexité en devant gérer leur destruction. En plus ils utilisent le COW.
    Je me suis peut être mal exprimé mais j'étais en train de dire que les objets COW étaient bon candidats pour un stockage non-pointeur dans un classe.

  6. #6
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par _skip Voir le message
    Alors t'es sûr de ça? Parce que selon mes connaissances (plus limitées que les tiennes sans doute je l'admet) c'est l'ordre inverse de complétion des constructeurs qui joue et non pas l'ordre d'invocation.
    J'ai pas tous compris Je vais me faire un petit code. Mais je suis quasiment sure de moi. Ce qui est sure est que l'odre de destruction des membres est dans le sens inverse de l'ordre de construction.

    D'ailleurs pour cause, dans le destructeur de monObj, tu es libre d'accéder aux propriétés des objets membres (ici m_timer), ce qui devrait signifier qu'il n'est pas liquidé.
    la fonction que l'on appel destructeur est là pour permettre de faire des traitement sur l'instance avant la destruction mémoire. Donc oui tu y as accès. Mais une fois sorti de la fonction, la destruction mémoire commence.

  7. #7
    Membre éprouvé
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Par défaut
    Citation Envoyé par yan Voir le message
    J'ai pas tous compris Je vais me faire un petit code. Mais je suis quasiment sure de moi. Ce qui est sure est que l'odre de destruction des membres est dans le sens inverse de l'ordre de construction.
    Mais tu parles d'ordre inverse d'invocation des constructeurs, or moi je veux dire par ordre inverse de complétion, (ordre de complétion = l'ordre dans lequel les constructeurs *retournent*).

    la fonction que l'on appel destructeur est là pour permettre de faire des traitement sur l'instance avant la destruction mémoire. Donc oui tu y as accès. Mais une fois sorti de la fonction, la destruction mémoire commence.
    Si l'objet membre a été liquidé, soit ça va planter, soit faire des trucs barges je dirai. Ca m'étonnerait vachement que ça marche *par bol* comme tu le dis.

  8. #8
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Voici un code. Ca sera peut être plus claire. J'ai l'impression que l'on dit la même chose.
    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    #include <QtCore>
     
    struct A
    {
        A() {qDebug() <<"A"; }
        ~A() {qDebug() <<"-A"; }
    };
     
    struct B
    {
        B() {qDebug() <<"B"; }
        ~B() {qDebug() <<"-B"; }
    };
     
    struct C
    {
        A a;
        B b;
        C() {qDebug() <<"C";}
        ~C() {qDebug() <<"-C";}
    };
    struct D
    {
        B b;
        A a;
     
        D() {qDebug() <<"D";}
        ~D() {qDebug() <<"-D";}
    };
     
    struct E
    {
        B b;
        A a;
     
        E():a(),b() {qDebug() <<"E";}
        ~E() {qDebug() <<"-E";}
    };
    int main(int argc, char *argv[])
    {
     
        {
            qDebug()<<"const";
             C c;
            qDebug()<<"dest";
        }
        {
            qDebug()<<"const";
             D d;
            qDebug()<<"dest";
        }
        {
            qDebug()<<"const";
             E e;
            qDebug()<<"dest";
        }
       return 0;
    }


    Si l'objet membre a été liquidé, soit ça va planter, soit faire des trucs barges je dirai.
    si a cause du lien parent/enfant un membre (non pointeur) est détruit oui ca fait n'importe quoi. C'est pour cela que c'est très risqué avec les QWidget. Avec les autres, comme la destruction du this est faite après eux, y as pas de problème. Plus exactement, c'est le destructeur du QObject qui va détruire les QObject enfants. Mais comme les membres sont détruit avant cette appel, il n'y as pas de problème.

    Ca m'étonnerait vachement que ça marche *par bol* comme tu le dis.
    ? j'aimais dit cela

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

Discussions similaires

  1. petite question rapide sur boucle for
    Par KateA dans le forum C
    Réponses: 15
    Dernier message: 08/03/2010, 23h59
  2. Réponses: 15
    Dernier message: 03/08/2009, 23h08
  3. petite question générale sur index unique
    Par ctobini dans le forum Requêtes
    Réponses: 2
    Dernier message: 07/02/2008, 15h45
  4. Petite question générale sur Javascript
    Par skywaukers dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 02/11/2007, 17h49
  5. Petite question rapide sur allocation mémoire
    Par adn013 dans le forum Langage
    Réponses: 5
    Dernier message: 11/06/2007, 16h10

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