c'est toujours d'actualité : je conseille de l'utiliser.
c'est devenu obsolète : à oublier !
Seulement s'il est défini dans le header, et dans ce cas:
- soit il est défini hors de la classe, et explicitement déclaré inline pour avoir un linkage faible
- soit il est défini dans la classe et donc (si je me souviens bien) implicitement inline.
Note: Je suppose la LTCG désactivée dans le cas présent. De toute façon, elle ne fait que repousser les frontières, pas les supprimer complètement.
- S'il est défini en-dehors de la classe, ce n'est pas un accesseur (ou il est friend, mais il devrait être dans la classe)
- Oui, il est implicitement inline, c'est le but
LTCG, ça ne marche pas encore, et ça sera toujours à la traîne par rapport à l'utilisation correct du langage (encore testé récemment sur le compilateur Intel qui plantait lamentablement sur un code qu'il passe sans pb sans).
Note: par "défini hors de la classe", je voulais juste dire ceci:
Déclaré dans la classe, défini en dehors (mais ici, inline et dans le header, ce qui est la même chose que le définir dans la classe).
Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 //UneClasse.h class UneClasse { private: int x; public: void CalculerX(int toto, int tata, int titi); int GetX() const; }; inline int UneClasse::GetX() const { return x; }
ah, OK
J'ai pour principe d'écrire le code dans la classe si c'est pour un en-tête. C'est plus ou moins ce qui est proposé dans Clean Code.
Ce n'est pas toujours possible pour des histoires d'inter-dépendances.J'ai pour principe d'écrire le code dans la classe si c'est pour un en-tête.
(T::foo utilise un U, mais U a besoin que T soit non-abstrait)
Dans la dernière boite où j'ai bossé, il y avait le même genre de classe Vector mathématique templaté où la plupart des operateurs et accesseurs étaient inline.Bon, aujourd'hui j'ai passé un autre entretien où j'ai mis le nez dans le code de leur logiciel etc... et en voyant un header de classe chargée d'effectuer des operations mathématiques (du type vecteurs etc...), y'avait du inline partout, et quelque part, j'ai trouvé ça... rassurant. En fait, je pense qu'au niveau technique l'utilité de ce mot-clé est réellement contestable (je suis d'accord avec Matthieu au sujet du problème de template, pour moi cette utilisation de inline est une pirouette qui sert à masquer un autre problème en fait).
En fait je me suis demandé si c'était vraiment important alors j'ai enlevé les inline pour voir.
La conséquence était qu'en debug il y avait a la fois une perte de vitesse visible et une augmentation de la taille de l'executable (sur NDS, donc ça posait problème) - la classe étant beaucoup utilisé (jeu vidéo oblige).
En "release" il n'y avait pas de différence parceque le compilateur (CodeWarrior) était configuré pour faire de l'inlining agressif dans ce mode.
Dans ce cas l'inlining avait un interet essentiel.
Dans mes projets actuels je n'utilise pas inline, je fais confiance au compilateur (essentiellement VC), suivant ce que j'ai lu ici et dans des tas de bouquins. Je n'ai toutefois pas les même contraintes (pc).
En revanche comme dit auparavant par d'autres je pense que je prendrais en compte l'inlining si j'ai besoin de faire de l'optimization (mais après d'autres techniques et mesures) mais aussi si j'ai besoin de rendre l'application plus rapide en debug. Visiblement inline permet d'aider le compilateur a inliner en debug, ce qui aide énormément dans le domaine du jeu vidéo (où dans pas mal de type de jeux on se retrouve a debugger exclusivement en Release ou equivalent parceque sinon le tout est tout simplement trop lent).
Par contre je me méfie quand même quand je vois du code des autres où il y a des fonctions inline.
Je ne m'avancerai pas là dessus. Je n'ai pas (encore) vérifié avec VC9. Je n'utilise pas gcc. En revanche je sais que par exemple CodeWarrior le fait () et que c'est le compilateur "fourni de base" pour pas mal de consoles (Wii, GBA/NDS, PS2 il me semble). Le domaine du jeu vidéo sur console n'est certainement pas le plus commun dans le developpement C++ mais il est tout de même important j'imagine.Pour 99% des compilateurs, il est possible de lui dire d'inliner indépendamment du mode debug ou non. Donc me^me dans ce mode, je ne vois pas l'intérêt du mot clé.
Autrement dit ton affirmation est poil abusive a mon gout; on va dire que la plupart des compilateurs ne font certainement pas la différence. Ca reste à prouver. (Mais c'est vrai que généralement je pars du principe que ça ne fais pas de différence, même si dans certains cas c'est faux).
Ce qui me fais penser... qu'un document rassemblant et comparant les comportements des différents compilateurs communs avec inline serait interessant et constructif pour cette discussion.
Edit> J'avais mal compris ta phrase : en fait dans l'exemple dont je parlais il y a bien une différence c'est qu'avec le mot clé cela permet de préciser qu'une partie uniquement du code est inline et non tout le projet contrairement aux configurations d'inlining qui s'appliquent a tout le projet. Dans l'exemple réel que je donne, seul la classe en question était inliné en debug et comme expliqué, ça avait un impact crucial (sans ça le jeu ne pouvait tout simplement pas tourner correctement en debug).
Bon bon bon,
Ma question de départ portait sur le mot-clé inline uniquement pour l'inlining. Mais C++ a cette particularité que pas mal de mot-clés ont des utilisations au delà de ce leur utilité "initiale". Bref.
J'ai fait un autre entretien hyper technique avec 2 team leader d'un super gros projet C++ (350 développeurs rien qu'en France...), et là, tadaaaaaa : on m'a sorti l'argument qui fait que inline est toujours d'actualité même dans le cas de l'optimisation de getters : les DLLs. Et oui, quand il s'agit d'appeler une fonction exportée par une DLL, le compilateur ne peut pas l'inliner si sa définition n'est pas disponible dans le header... Donc, en bref, inline ne sert plus à rien pour vaincre les barrières d'une unité de compilation, mais il est toujours nécessaire pour dépasser les frontières d'un module utilisé dynamiquement.
C'est le problème des tests par écrit : on ne peut pas discuter avec l'auteur et savoir ce qu'il veut entendre / son niveau. Donc j'ai dit qu'il y avait un paradoxe à mixer virtual et inline (indirection obligatoire via la vtable)... tout en précisant que le compilateur pouvait dans certaines conditions outrepasser la vtable et effectuer un appel direct, et que donc dans ce cas un inlining était possible. Mais que même dans ce cas, le mot-clé inline en lui-même etait superflu du fait que le compilo sait faire tout seul l'optimisation jusqu'au bout.
En recherchant sur le net, j'ai trouvé cet article :
http://msdn.microsoft.com/en-us/magazine/cc301407.aspx
et l'auteur mentionne le fait que sur certains (vieux ?) compilateurs on peut éventuellement se retrouver avec plusieurs vtables pour un même objet si les fonctions virtuelles sont inlinées, bien que le standard C++ interdise cela.
Puisqu'on va loin dans cette discussion, continuons avec les risques de fournir l'implémentation dans un header. Le compilo se fiche d'avoir plusieurs définitions, ok. Mais sur un gros projet, il est relativement facile de générer plusieurs définitions... différentes. Et alors...
Un jour, le soft que je développais fonctionnait sans problème en debug et plantait en release avec l'optimisation WPO (LTCG). J'ai mis 2 jours à localiser le problème : je n'avais pas les mêmes flags de compilation dans tous les modules. Conséquences : le code des templates n'était pas compilé de la même manière dans tous les modules (c'était lié aux trucs de "sécurité" de la STL de VC++ : flag _SECURE_SCL etc...). Ce non respect du standard C++ (multiples définitions différentes d'un même code template) ne se manifestait qu'avec l'optimisation sur l'ensemble du programme.
Il existe aussi les fonctions intrinsèques :
http://msdn.microsoft.com/en-us/libr...43(VS.80).aspx
A l'exception de leur appel depuis un autre module comme une dll, comme expliqué plus haut.
Mouais... Je ne suis pas hyper convaincu. Pour la bonne raison que si les perfs comptent de manière si sensible que l'inlinig soit rentable, autant supprimer la DLL et faire du link statique, on aura les mêmes avantages pour toutes les fonctions, pas seulement les getters (qui d'ailleurs s'ils sont trop monbreux et ont un impact sur les perfs sont probablement signe de mauvais design). J'ai déjà gagné 10% de perf sur du code déjà assez optimisé simplement en linkant statiquement ce qui avant était une DLL.
Ca ne me surprend pas, ça a aussi généralement un intérêt positif au niveau de la taille du code (élimination du code mort...), sans parler du temps d'initialisation plus rapide de l'appli (on économise toute l'édition de liens dynamique).
On a parlé rapidement de pourquoi ils utilisaient des dlls. Au delà du fait qu'ils utilisent beaucoup COM, ils m'ont dit qu'ils sont aussi obligés pour des raisons de redistribution / de mises à jours (ils ont 255 composants assemblés / vendus à la demande du client). Ils m'ont mentionné le gain de temps d'un point de vue recompilation (cela dit c'est un argument valable pour le développement / en debug, mais beaucoup moins pour builder une version finale). D'ailleurs, c'est un effet de bord des fonctions inline à ce niveau : en changer l'implémentation force à recompiler non seulement la DLL mais aussi toutes celles qui l'utilise. C'est ce qu'ils avaient à reprocher aux fonctions inline.
Toujours pas compris le coup du chargement dynamique. Ce qu'ils voulaient dire, c'est qu'inline pouvait les empêcher d'utiliser la bibliothèque parce que la fonction n'était pas exportée ? De toute manière, l'accesseur ne peut jamais être inliné puisqu'on n'a pas le code correspondant
Quand une fonction est mise en inline dans le .h d'une DLL, elle pourra être effectivement inlinée dans le code de la DLL, mais aussi dans le code appelant. En pratique, ça revient à définir ce code 2 fois, dans la DLL et dans son client.
C'est moi qui dit ça. Pour chaque DLL liée à ton exe, le loader de l'OS doit déjà localiser le fichier sur le disque puis le charger en mémoire (ce qui peut provoquer un conflit du fait qu'une autre DLL occupe déjà la plage d'adresse de "préférence" de ladite dll, ce qui entraine un mécanisme couteux de relocation -> le rebasing), mais aussi effectue la liaison dynamique entre tous les symboles importées (sous forme de chaînes de caractères souvent... donc potentiellement des milliers de strings à comparer / matcher). Si on utilise plusieurs grosses DLL, ça finit par se ressentir même de nos jours. Mais si on link statiquement, on économise tout cela (ou plutôt on le paye une seule fois au moment du link).
Non non, ils utilisent inline. L'effet de bord, c'est que si tu modifies l'implémentation d'une fonction inline, tu dois recompiler tout le code client qui inclut ce header (normal). Sur un projet de plusieurs millions de lignes de codes, ça les agace un peu (normalement recompiler la DLL suffit).
Ah, OK... Je comprend mieux (ou plutôt j'avais rien compris de la problématique qu'ils avaient )
Puisqu'on parle des conséquences avancées de l'utilisation de inline notamment avec les DLLs, je viens de lire ceci :
http://techbase.kde.org/Policies/Bin...ine_a_function
En clair, il ne faut pas inliner une fonction exportée si vous souhaiter conserver une compatibilité binaire avec votre dll : vue qu'elle aura été inlinée dans le code des DLLs utilisatrices, le changement de son implémentation dans la DLL passera inaperçu / sera ignoré.
Donc si on modifie une fonction inline exportée, non seulement il faut recompiler toutes les DLLs utilisatrices, mais aussi les redistribuer chez le client même si leur code source n'a pas été modifié. A utiliser avec modération donc vu que la modification d'une seule ligne de code dans une fonction inline peut nécessiter un patch chez le client de plusieurs dizaines / centaines de DLLs.
Ça, il suffit de faire du prelinking, pas besoin de lier statiquement.sans parler du temps d'initialisation plus rapide de l'appli (on économise toute l'édition de liens dynamique).
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