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

Affichage des résultats du sondage: Que pensez-vous du mot-clé inline aujourd'hui :

Votants
36. Vous ne pouvez pas participer à ce sondage.
  • c'est toujours d'actualité : je conseille de l'utiliser.

    16 44,44%
  • c'est devenu obsolète : à oublier !

    20 55,56%
Langage C++ Discussion :

Intérêt de "inline" de nos jours : pour ou contre ?


Sujet :

Langage C++

  1. #81
    Débutant  
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Points : 217
    Points
    217
    Par défaut
    Attention, la présence du 0xCCCCCCCC montre que c'est encore une compilation en Debug.
    Exact, mais en mode Release, on ne voit plus la différence. Je pense que le compilo optimise aussi max.

  2. #82
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    De plus, si max, max2 et main sont dans un même fichier, il faut tenir compte du fait que la définition de max vaut déclaration, et que la définition étant donnée au moment de la déclaration, la fonction est réputée inline.

    Tu aurais sans doute un résultat bien plus fiable si tu veillait à avoir effectivement une déclaration et une implémentation séparée, sous la forme de
    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
    int max(int a, int b);
    inline max2(int a, int b);
    int main(){
       int al=5,bl=0;
       int mo=max(al,bl);
        mo=max2(al,bl);
    }
    int max(int a, int b)
    {
        return a<b? a:b;
    }
    inline max2(int a, int b)
    {
        return a<b? a;b;
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #83
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par deubelte Voir le message
    Exact, mais en mode Release, on ne voit plus la différence. Je pense que le compilo optimise aussi max.
    Les compilateurs savent si bien optimiser que probablement ton main est vide en release

  4. #84
    Débutant  
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Points : 217
    Points
    217
    Par défaut
    En ce moment je passe des entretiens et donc des tests techniques C++, et j'ai eu droit à une question sur "virtual inline".
    Moi, en ce moment, j'étudie qqch qui parle exactement de virtual inline, mais pour le cas particulier des destructeurs. Si j'ai bien compris, inline insert le code dans la fonction main, ce qui fait que la fonction n'a plus vraiment d'adresse. Le problème est que virtual crée automatiquement une adresse mémoire pour la vtbl afin que le pointeur vptr pointe entre autre sur cette adresse.
    ce qui fait que l'apport de inline est annulé par virtual

    Je reproduis le commentaire du livre:


    Because your destructor is virtual, its address must be entered into the class's vtbl. But inline
    functions aren't supposed to exist as freestanding functions (that's what inline means, right?), so special measures
    must be taken to get addresses for them. The bottom line is this: if you declare a
    virtual destructor inline, you're likely to avoid function call overhead when it's invoked, but your compiler will
    still have to generate an out-of-line copy of the function somewhere, too.

  5. #85
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par deubelte Voir le message
    Moi, en ce moment, j'étudie qqch qui parle exactement de virtual inline, mais pour le cas particulier des destructeurs. Si j'ai bien compris, inline insert le code dans la fonction main, ce qui fait que la fonction n'a plus vraiment d'adresse. Le problème est que virtual crée automatiquement une adresse mémoire pour la vtbl afin que le pointeur vptr pointe entre autre sur cette adresse.
    ce qui fait que l'apport de inline est annulé par virtual
    A vrai dire, l'inlining d'un destructeur virtuel n'a, purement et simplement, aucun sens (pas plus d'ailleurs que l'inlining de n'importe quelle autre fonction virtuelle ).

    En effet, lorsque tu déclare (dans la classe parent) une fonction virtuelle, c'est comme si tu disais au compilateur:
    Le comportement de cette fonction peut changer en fonction du type réel (dynamique) de l'objet au départ duquel la fonction est invoquée
    Or, il faudra déterminer dynamiquement (à l'exécution) le type réel de l'objet uniquement si... on le fait passer pour un objet du type de la classe parent (ancêtre).

    Cela implique fatalement que... le type réel de l'objet est... inconnu au moment de la compilation.

    Dés lors, comment voudrais tu que le compilateur sache par quoi il devra remplacer l'appel, alors qu'il ne sait même pas exactement au départ de quel type d'objet cet appel est effectué

    Bien sur, si tu as, simplement un
    ou un
    (étant entendu que Derivee hérite de Base ) il n'y aura aucun problème pour déterminer par quoi remplacer l'appel d'une fonction virtuelle, mais ce n'est, typiquement, pas dans ce cas que la virtualité intervient.

    Par contre, la virtualité des fonction interviendra forcément si tu as un
    ou un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Base * ptr=new Derivee;
    et là, il sera tout à fait hors de question pour le compilateur d'inliner l'appel, simplement, parce qu'il doit s'assurer de passage par... la table de fonctions virtuelles afin d'être sur que version de la fonction invoquée correspond bien au type dynamique au départ duquel elle est invoquée.
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #86
    Membre éclairé Avatar de metagoto
    Profil pro
    Hobbyist programmateur
    Inscrit en
    Juin 2009
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Hobbyist programmateur

    Informations forums :
    Inscription : Juin 2009
    Messages : 646
    Points : 845
    Points
    845
    Par défaut
    Citation Envoyé par koala01 Voir le message
    A vrai dire, l'inlining d'un destructeur virtuel n'a, purement et simplement, aucun sens (pas plus d'ailleurs que l'inlining de n'importe quelle autre fonction virtuelle ).
    Mais si le destructeur, virtuel ou non, est défini dans la classe, la fonction est "inline". Si en plus le destructeur est vide (ce qui arrive), là je pense qu'un compilo pourrait vraiment inliner.

    Aussi, rien n'empêche de manipuler un objet par son type statique et donc potentiellement de caller son destructeur, au demeurant inline et virtuel (dans la déclaration). Ca ne me parait pas incompatible, et on tombe sur la citation précédente de deubelte.

  7. #87
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par metagoto Voir le message
    Mais si le destructeur, virtuel ou non, est défini dans la classe, la fonction est "inline". Si en plus le destructeur est vide (ce qui arrive), là je pense qu'un compilo pourrait vraiment inliner.
    A ceci près que la vtbl ne sera pas créée (ou en tout cas, le destructeur ne sera pas référencé dans la vtbl)...

    Cela compilera (comprend: le compilateur ne bronchera pas), mais l'éditeur de liens t'enverra cueillir des pâquerettes lorsqu'il s'agira de tout remettre en ordre.
    Aussi, rien n'empêche de manipuler un objet par son type statique et donc potentiellement de caller son destructeur, au demeurant inline et virtuel (dans la déclaration). Ca ne me parait pas incompatible, et on tombe sur la citation précédente de deubelte.
    C'est sympa de me répéter (car j'ai aussi exprimé ce point de vue ), mais, encore une fois, tu risques fortement de te faire jeter par l'éditeur de liens
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #88
    Débutant  
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Points : 217
    Points
    217
    Par défaut
    A ceci près que la vtbl ne sera pas créée (ou en tout cas, le destructeur ne sera pas référencé dans la vtbl)...
    Et pour quelles raisons? Est-ce parce que le destructeur est déclaré dans la classe?


    Dans VC2010, est-il possible d'acceder à la vtbl?

  9. #89
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par deubelte Voir le message
    Dans VC2010, est-il possible d'acceder à la vtbl?
    Directement, non. Cependant, tu peux voir la façon dont c'est utilisé en regardant le code ASM. Regardes ici : Les fonctions virtuelles en C++ : Comment ça marche ?

  10. #90
    Membre confirmé Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Points : 633
    Points
    633
    Par défaut
    Héhé, c'est le fameux problème du :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    struct A {
       virtual ~A() {};
    }
    Je me suis toujours demandais, mais il faudrait tester, si l'inlining dans se cas n'inlinerai pas plutôt les processus de résolution de virtualité. [edit] <= Stupide ! Mais est-il possible d'inliné la fonction dans la résolution de polymorphisme elle même ?


    [edit] Au passage, c'est loin d'être "interdit".

    Par défaut, je pensais qu'un virtual inline procédé comme ceci :
    En cas d'appel polymorphique, on résout celui-ci.
    Sinon, en cas d'appel direct, on applique le cas classique.
    The mark of the immature man is that he wants to die nobly for a cause, while the mark of the mature man is that he wants to live humbly for one.
    --Wilhelm Stekel

  11. #91
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Citation Envoyé par koala01 Voir le message
    A ceci près que la vtbl ne sera pas créée (ou en tout cas, le destructeur ne sera pas référencé dans la vtbl)...

    Cela compilera (comprend: le compilateur ne bronchera pas), mais l'éditeur de liens t'enverra cueillir des pâquerettes lorsqu'il s'agira de tout remettre en ordre.

    C'est sympa de me répéter (car j'ai aussi exprimé ce point de vue ), mais, encore une fois, tu risques fortement de te faire jeter par l'éditeur de liens
    Je ne pense pas.

    Le compilateur sait à la compilation si un appel est virtuel ou pas. Donc, il sait s'il peut inliner le code du destructeur, ou s'il doit passer par le destructeur virtuel.

    C'est le sens de :

    The bottom line is this: if you declare a virtual destructor inline, you're likely to avoid function call overhead when it's invoked, but your compiler will still have to generate an out-of-line copy of the function somewhere, too.
    Qui grosso-modo dit que si tu déclares ton destructeur virtuel inline, le compilateur pourra l'inliner dans certains cas, mais devra de toute manière générer une version non-inline dudit destructeur.

  12. #92
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    +1
    Citation Envoyé par deubelte Voir le message
    Le problème est que virtual crée automatiquement une adresse mémoire pour la vtbl afin que le pointeur vptr pointe entre autre sur cette adresse.
    ce qui fait que l'apport de inline est annulé par virtual
    Je crois que la génération ou non de code pour une fonction n'est pas lié à l'inline de celle-ci (mais peut en être une conséquence possible). Il existe plusieurs cas où une fonction, même inline, DOIT avoir un code généré ainsi qu'une adresse ; bien sûr si elle est membre virtuelle, mais aussi si l'on prend son adresse (par exemple pour la stocker), si elle est récursive, si elle est exportée, si le compilateur décide de ne pas l'étendre à certains endroits. En revanche, cela n'affecte pas la possibilité de voir cette fonction étendue à d'autres endroits (et de gagner un appel de fonction). Donc l'apport du inline n'est pas annulé.
    Inversement, une fonction non inline peut être supprimée, à l'édition des liens, si elle n'est jamais appelée (ce qui a peu d'intérêt en soi ).
    Citation Envoyé par koala01 Voir le message
    A vrai dire, l'inlining d'un destructeur virtuel n'a, purement et simplement, aucun sens (pas plus d'ailleurs que l'inlining de n'importe quelle autre fonction virtuelle ).
    Il est pourtant possible dans une classe fille d'appeler une fonction membre héritée virtuelle de manière "non polymorphique". Cela est même toujours le cas pour un destructeur, qui appel automatiquement ses ancêtres.
    [HS] Après, il faut tout de même être prudent avec les destructeurs inline (un destructeur vide peut quand même être volumineux et un destructeur inline est sujet aux mêmes dangers qu'un destructeur auto généré -> cf. destruction d'un type incomplet).[HS]

  13. #93
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par gb_68 Voir le message
    Il est pourtant possible dans une classe fille d'appeler une fonction membre héritée virtuelle de manière "non polymorphique".
    Le fait est que la gestion de l'inlining se fait... à la compilation, alors que la gestion de la virtualité ne se fait ... qu'au runtime...

    Comme on l'a vu, en simplifiant à l'extrême, l'inlining va dire au compilateur de remplacer l'appel de la fonction par le code de celle-ci (même s'il y a certaines restrictions )

    Par contre, l'appel d'une fonction virtuelle va dire au compilateur de rajouter du code allant chercher dans la vtbl l'adresse réelle de la fonction qui est appelée, et ce passage par la vtbl sera obligatoire dés le moment où tu travailles avec une référence ou un pointeur, pour la simple et bonne raison qu'il sera incapable de déterminer si la référence (ou le pointeur) ne fait pas passer une instance d'une classe dérivée pour la classe de base.

    Le compilateur ne pourra donc quasiment jamais inliner l'appel d'une fonction virtuelle.[EDIT]Du moins, jamais si l'appel est suspecté d'être polymoprhique[/EDIT]

    De plus, on remarque que, même si c'est du à un bug, certains compilateurs ne créent effectivement pas de vtbl s'il n'y a aucune fonction virtuelle non inline (c'était, me semble-t-il, le cas pour a version antérieure de MinGW), ce qui se traduit immanquablement par une erreur à l'édition de liens
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  14. #94
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Le fait est que la gestion de l'inlining se fait... à la compilation, alors que la gestion de la virtualité ne se fait ... qu'au runtime...
    Oui, mais à la compilation la nature de l'appel est définie (virtuel ou non virtuel) et le code est généré en fonction (non virtuel -> possibilité d'inline ?, virtuel -> accès à la vtbl). Même pour un fonction déclarée virtuelle, il existe des cas d'appel où la virtualité n'entre pas en compte.
    Citation Envoyé par koala01 Voir le message
    Le compilateur ne pourra donc quasiment jamais inliner l'appel d'une fonction virtuelle.[EDIT]Du moins, jamais si l'appel est suspecté d'être polymoprhique[/EDIT]
    L'exemple que je donnais sur la classe fille appelant une fonction membre héritée virtuelle de manière "non polymorphique" n'est pas si rare (cf. cas des destructeurs).
    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
    class Base
    {
    public:
       virtual ~Base()
       { /*...*/ }
    };
     
    class Deriv  : public Base
    {
    public:
       virtual ~Deriv();
       /*...*/
    };
     
    void SomeFunction()
    {
       Base * ptr =new Deriv(); 
       /*...*/
       delete ptr; // <- ici, le polymorphisme entre en jeu
    }
     
    Deriv::~Deriv()
    {
       /*...*/
     
       // appel automatique de Base::~Base() <- ici pas de polymorphisme,
       // l'inline est possible   
    }
    Un destructeur virtuel inline semble donc plus que cohérent si l'on souhaite gagner un appel de fonction dans les destructeurs des classes dérivées.

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