web-dev-qa-db-fra.com

Est-ce une bonne pratique de mettre en ligne des getters et setters?

public:
     inline int GetValue() const {
          return m_nValue;
     }
     inline void SetValue(int nNewValue) {
          this -> m_nValue = nNewValue;
     }

Le Learn C++, ils ont dit que cela fonctionnerait plus rapidement. J'ai donc pensé que ce serait génial à utiliser sur les getters et les setters. Mais peut-être y a-t-il des inconvénients?

70
Martijn Courteaux

Je n'insère rien tant qu'un profileur ne m'a pas spécifiquement dit que le non-alignement entraîne un problème de performances.

Le compilateur C++ est très intelligent et incorporera presque certainement automatiquement une fonction aussi simple comme celle-ci pour vous. Et généralement, il est plus intelligent que vous et fera un bien meilleur travail pour déterminer ce qui devrait ou ne devrait pas être intégré.

J'éviterais de penser à quoi faire ou ne pas aligner et me concentrer sur la solution. Ajouter le mot clé inline plus tard (ce qui n'est pas une garantie de BTW en ligne) est très facile à faire et des emplacements potentiels peuvent être facilement trouvés avec un profileur.

56
JaredPar

Si vous les écrivez dans la définition, ils sont considérés comme inlinepar défaut.

Cela signifie qu'elles seront autorisées dans plusieurs unités de compilation (puisque les définitions de classe elles-mêmes apparaissent généralement dans plusieurs unités de compilation), pas qu'elles le seront réellement être en ligne.

29
AraK

Il s'agit d'une mauvaise pratique dans les API publiques. Toute modification de ces fonctions nécessite une recompilation de tous les clients.

En général avoir des getters et setters montre une mauvaise abstraction, ne le faites pas. Si vous allez constamment aux données brutes d'une autre classe, vous devrez probablement réorganiser vos classes, mais plutôt réfléchir à la manière dont vous souhaitez manipuler les données au sein d'une classe et fournir des méthodes appropriées pour le faire.

16
Greg Domjan

Points négatifs:

  1. Le compilateur est libre de vous ignorer.

  2. Toute modification de ces fonctions nécessite une recompilation de tous les clients.

  3. Un bon compilateur incorporera de toute façon les fonctions non incorporées quand cela sera approprié.

10
Edward Strange

Je voudrais également ajouter que, à moins que vous n'effectuiez des millions de jeux/ensembles par image, il est à peu près inutile qu'ils soient en ligne ou non. Honnêtement, cela ne vaut pas la peine de dormir.

En outre, gardez à l'esprit que le simple fait de placer le mot "en ligne" devant votre déclaration + définition ne signifie pas que le compilateur alignera votre code. Il utilise diverses heuristiques pour déterminer si cela a du sens, ce qui est souvent le compromis classique entre vitesse et taille. Il y a cependant le mot-clé '__forceinline' de force brute, à bail dans VC++ (je ne sais pas ce que c'est dans GCC), qui trébuche sur les compilateurs de fantaisie heuristique. Je ne le recommande vraiment pas du tout, et en plus une fois que vous portez sur une architecture différente, ce sera probablement incorrect.

Essayez de mettre toutes les définitions de fonction dans le fichier d'implémentation et de laisser les déclarations pures pour les en-têtes (à moins bien sûr que vous soyez un métaprogrammation de modèle (STL/BOOST/etc), auquel cas, à peu près tout est dans les en-têtes;))

L'un des endroits classiques que les gens aiment intégrer (au moins dans les jeux vidéo, d'où je viens) est dans les en-têtes mathématiques. Les produits croisés/à points, les longueurs de vecteur, l'effacement de matrice, etc. sont souvent placés dans l'en-tête, ce qui, à mon avis, n'est pas nécessaire. 9/10 cela ne fait aucune différence dans les performances, et si jamais vous avez besoin de faire une boucle serrée, comme transformer un grand tableau vectoriel par une matrice, vous feriez probablement mieux de faire manuellement les mathématiques en ligne, ou encore mieux de le coder dans assembleur spécifique à la plate-forme.

Oh, et un autre point, si vous sentez que vous avez vraiment besoin d'une classe pour être plus de données que de code, pensez à utiliser une bonne vieille structure, qui n'apporte pas le bagage d'abstraction OO avec elle, c'est pourquoi il est là. :)

Désolé, je ne voulais pas continuer autant, mais je pense simplement qu'il est utile de prendre en compte les cas d'utilisation du monde réel, et de ne pas trop se bloquer sur les paramètres du compilateur pédant (croyez-moi, j'y suis allé;))

Bonne chance.

Shane

5
Shane

Le code se compile un peu plus longtemps et vous perdez l'encapsulation. Tout dépend de la taille du projet et de sa nature. Dans la plupart des cas, il est acceptable de les rendre en ligne s'ils n'ont pas de logique complexe.

BTW, vous pouvez ignorer inline si vous implémentez directement dans la définition de classe.

2
Paul

En mettant le code dans l'en-tête, vous exposez votre fonctionnement de classe interne. Les clients peuvent voir cela et faire des hypothèses sur le fonctionnement de votre classe. Cela peut rendre plus difficile de changer votre classe plus tard sans casser le code client.

2
Tim Rupe

Le mot clé en ligne n'a pas de sens dans votre cas

Le compilateur alignera votre fonction s'il le peut et le souhaite, quel que soit le mot clé.

Le mot clé inline affecte la liaison et non la mise en ligne. C'est un peu déroutant, mais lisez-le.

Si la définition se trouve dans une unité de compilation différente (fichier source après le préprocesseur, essentiellement) que l'appel, l'inline ne sera possible que si l'optimisation du projet entier et la génération du code temporel de la liaison sont activées. L'activer augmente considérablement le temps de liaison (car il recompile pratiquement tout dans l'éditeur de liens), mais peut évidemment améliorer les performances. Je ne sais pas si elle est activée ou désactivée par défaut dans GCC et VS.

1
Gal

Je dirais que vous n'avez pas besoin de vous en préoccuper. Lisez la section FAQ sur l'inlining .

1
mkluwe

Pas besoin, faites confiance aux compilateurs, au moins pour de telles optimisations!
"Mais pas toujours"

1
Numan

Je dois dire que je n'ai pas la forte aversion pour cette pratique que les autres sur ce fil semblent avoir. Je conviens que le gain de performances de l'inline est négligeable dans tous les cas, sauf dans les plus utilisés. (Et oui, j'ai ai rencontré de tels cas dans la pratique.) Lorsque je fais ce type d'inline, je le fais pour plus de commodité, et généralement juste pour des lignes simples comme celle-ci. Dans la plupart de mes cas d'utilisation, la nécessité d'éviter la recompilation côté client si je les change n'est tout simplement pas si forte.

Oui, vous pouvez supprimer le inline, comme cela est impliqué par le placement de l'implémentation.

De plus, je suis un peu surpris de la véhémence contre les accesseurs. Vous pouvez à peine éternuer à une classe dans n'importe quel langage OO sans en souffler quelques-uns, et ils sont après tout une technique valide pour abstraire l'implémentation de l'interface, donc c'est un peu masochiste de les déclarer mauvais OO pratique. Il est bon conseil de ne pas écrire aveuglément les accesseurs, mais je vous conseille également de ne pas vous laisser emporter dans le zèle pour les éradiquer.

Prenez ça, puristes. :-)

0
Owen S.