Les accesseurs et Mutateurs. Est-il des performances?
j'ai un moteur de système de particules dans mon projet C++ et les particules elles-mêmes sont juste des structures de variables sans fonctions. Actuellement, chaque particule (particule) est mise à jour à partir de sa classe mère (système de particules) en ayant ses variables accessibles directement. E. g.
particle.x += particle.vx;
je suis cependant en train de débattre en utilisant des getters et des setters comme ceci:
particle.setX( particle.getX()+particle.getVX() );
Ma question est: Est-il des performances de l'appel de getters et setters comme vous êtes contre l'accès direct aux données?
après tout, j'ai beaucoup de particules à mettre à jour...
4 réponses
Setters et getters ont une surcharge de performance lorsqu'il n'est pas optimisé. ils sont presque toujours optimisés sur les compilateurs qui font l'optimisation de temps de lien. Et sur les compilateurs qui ne le font pas, s'ils ont connaissance de l'organisme de fonction (c'est-à-dire pas seulement un prototype), il sera optimisé.
cependant, vous utilisez getters et setters sont là parce que vous pourriez vouloir obtenir ou le réglage de cette variable pour avoir des effets secondaires supplémentaires. Comme changer la position d'un objet change également la position des objets voisins dans une simulation physique ou une telle.
enfin, la charge d'une opération getter et setter, dans le contexte du code optimisé, est très petite, ne mérite pas de s'inquiéter à moins que le code ne soit chaud. Et si c'est chaud, c'est si facile de simplement déplacer le getter ou le setter vers le fichier d'en-tête et de le mettre en ligne.
donc pour résumer, les getters et les setters valent bien les frais généraux mineurs ou inexistants, car ils vous permettent de spécifier très spécifiquement ce qui peut et ne peut pas se produire avec votre objet, et il vous permet également de mobiliser tous les changements.
les Getters et les setters sont des signes que votre classe n'est pas conçue d'une manière utile: si vous ne rendez pas le comportement externe abstrait de l'implémentation interne, il n'y a aucun intérêt à utiliser une interface abstraite en premier lieu, vous pourriez aussi bien utiliser une vieille structure simple.
pensez à ce que vous opérez vraiment besoin. C'est presque certainement accès direct aux coordonnées x - y - et z-De La position et de l'impulsion, vous voulez plutôt les traiter comme des quantités vectorielles (au moins dans la plupart des calculs, ce qui est tout ce qui est pertinent pour l'optimisation). Vous voulez donc mettre en œuvre une interface vectorielle*, où les opérations de base sont l'addition vectorielle, l'échelle et le produit intérieur. Pas d'accès par composant; vous avez probablement besoin de le faire parfois aussi bien, mais cela peut être fait avec un seul std::array<double,3> to_posarray()
membre ou quelque chose comme ça.
Lorsque le composants internes x
,y
... vz
ne sont pas accessibles de l'extérieur, vous pouvez alors changer en toute sécurité l'implémentation interne sans freiner aucun code en dehors de votre module. C'est à peu près tout le problème des getters/setters; cependant, lorsqu'on utilise ces derniers, il n'y a qu'une optimisation possible: tout changement réel dans la mise en œuvre ralentit inévitablement les getters.
d'un autre côté, vous pouvez optimiser l'enfer d'une interface vectorielle, avec les opérations SIMD, les appels de bibliothèque externes (éventuellement sur du matériel accéléré comme CUDA) et semblables. Un "batch-getter" comme to_posarray
peut encore être implémenté de façon raisonnablement efficace, les setters à une seule variable ne le peuvent pas.
* je veux dire vecteur dans le sens mathématique ici, pas comme std::vector
.
les Getters et les setters permettent à votre code d'évoluer plus facilement à l'avenir, si l'obtention et la mise en place s'avèrent être des tâches légèrement plus compliquées. La plupart des compilateurs C++ sont assez intelligents pour inline ces méthodes simples et éliminent les frais généraux de l'appel de fonction.
Il pourrait y avoir plusieurs réponses à cette question, mais j'ai mis mes pensées ici.
pour la performance, le coût peut être ignoré pour un type de gousse simple. Mais il y a quand même un prix à payer, et ça dépend du type que tu retournes. Pour particule, il ne peut pas y avoir beaucoup de données. S'il s'agit d'une classe d'image (comme OpenCV cv::Mat), ou de données 3d (comme PolyData dans VTK), il est préférable que setter / getter traite les pointeurs / itérateurs que les données réelles pour éviter l'allocation de mémoire. problème.
quand vous voulez template things, le setter/getter peut être très utile pour éviter la conversion de type inexplicable. Un setter/getter peut être un moyen d'accéder à private / protected member, ce qui vous permet également d'éviter d'utiliser x comme nom commun de variable. De plus, le setter / getter peut renvoyer une référence Lvalue qui vous permet de faire particle.getX() = 10.0 ;