Exact, mais en mode Release, on ne voit plus la différence. Je pense que le compilo optimise aussi max.Attention, la présence du 0xCCCCCCCC montre que c'est encore une compilation en Debug.
c'est toujours d'actualité : je conseille de l'utiliser.
c'est devenu obsolète : à oublier !
Exact, mais en mode Release, on ne voit plus la différence. Je pense que le compilo optimise aussi max.Attention, la présence du 0xCCCCCCCC montre que c'est encore une compilation en Debug.
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
Ressources proposées par 3DArchi - Les fonctions virtuelles en C++ - Cours et tutoriels C++ - FAQ C++ - Forum C++.
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.En ce moment je passe des entretiens et donc des tests techniques C++, et j'ai eu droit à une question sur "virtual inline".
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.
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:
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).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
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
Code : Sélectionner tout - Visualiser dans une fenêtre à part Base mabase;
(é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.
Code : Sélectionner tout - Visualiser dans une fenêtre à part Derivee maderivee;
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 Base;
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.
Code : Sélectionner tout - Visualiser dans une fenêtre à part Base * ptr=new Derivee;
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
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.
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 liensAussi, 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.
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
Et pour quelles raisons? Est-ce parce que le destructeur est déclaré dans la classe?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)...
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 ?
Ressources proposées par 3DArchi - Les fonctions virtuelles en C++ - Cours et tutoriels C++ - FAQ C++ - Forum C++.
Héhé, c'est le fameux problème du :
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 ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 struct A { virtual ~A() {}; }
[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
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 :
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.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.
+1Je 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 ). 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]
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
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.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).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.
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 }
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager