1

Je veux implémenter une sorte d'objets mathématiques "en nombre" (disons, des éléments dans un groupe ou un anneau) en C++. Je suis sûr que je ne suis pas le seul à gérer ce problème, donc il peut y avoir beaucoup de discussions sur la meilleure façon de surcharger les opérateurs arithmétiques. Cependant, je n'ai pas trouvé de réponses satisfaisantes (même si j'étais peut-être trop paresseux pour googler plus).Quel est le "meilleur" moyen de surcharger les opérateurs arithmétiques en C++ moderne?

Disons que je veux surcharger l'opérateur « + » pour une classe A. Le problème est, il y a trop de surcharges différentes que je peux penser:

  1. opérateur + (const A & x, const A & y)
  2. opérateur + (const A & x, A & & y)
  3. opérateur + (A & & x, const A & y)
  4. opérateur + (A & & x, A & & y)
  5. A :: opérateur + = (const A & y) &
  6. A :: opérateur + = (const A & y) & &
  7. A :: operator + = (A & & y) &
  8. A :: opérateur + = (A & & y) & &

Première question. Est-ce que toutes ces surcharges sont nécessaires pour rendre les opérations sur les instances de A aussi efficaces et aussi importantes que "d'être comme des types primitifs"? Je pense que pour les cas "ordinaires", rvalue-qualifié A :: operator + = ne doit pas (ou ne devrait pas) être surchargé. Est ce bien? Je pense que tous 1-4 sont nécessaires. Par exemple, pour le cas 3, puisque x est déplacé, nous n'avons pas besoin d'allouer un nouvel espace pour contenir la valeur de retour, et nous pouvons réutiliser en toute sécurité le stockage d'allocation réservé pour x. Est ce bien?

Deuxième question. Je pense que toutes ces surcharges peuvent partager beaucoup de codes pour la plupart de ce genre de cas. Comment puis-je minimiser la duplication de code sans sacrifier les performances/etc.? Existe-t-il des techniques/idiomes spéciaux pour le faire? Je préfère les méthodes générales et extensibles, si elles existent.

Répondre

4

Il n'est pas possible de donner une réponse plus générale, car choisir le «meilleur» moyen impliquera une appréciation des détails de l'opération. Par exemple, le modèle le plus commun (que je donne ci-dessous) n'est pas très bon pour la Multiplication Matricielle, car dans ce cas, il est plus simple de déclarer une troisième matrice qui commence par zéro et lit les deux arguments. Vous pouvez également utiliser l'évaluation paresseuse, auquel cas cela ne s'applique pas.

Je vous recommande de vous assurer que votre code donne les bonnes réponses pour tous les cas, et vous pouvez vous soucier de la micro-optimisation plus tard une fois que votre programme fonctionne et une fois que vous avez plus d'expérience dans la langue.


Pour une classe où la façon la plus efficace de mettre en œuvre + est de modifier l'un des arguments, les deux cas suivants couvrent toutes les utilisations, avec la forte garantie d'exception:

A& A::operator+=(A const &y) { /* modify *this using y */ ; return *this; } 
A operator+ (A x, A const& y) { x += y; return x; } 

Pour en savoir plus explication sur ce que le code ci-dessus fait et pourquoi, voir le operator overloading megathread. En C++ 03, l'utilisation de A const& x au lieu de A x n'a pas beaucoup changé, mais en C++ 11 c'est légèrement plus optimal dans le cas où le premier argument est une valeur, car les ressources peuvent maintenant être volé du premier argument.

En ce qui concerne la décision d'utiliser les qualificatifs ref sur operator+=. Il n'y a aucun avantage à la surcharge séparée pour & et &&. Si vous avez vu des personnes utilisant &, la raison d'être n'est pas de surcharger, mais de donner une erreur de compilation pour essayer d'utiliser += sur un rvalue; avec la logique étant que c'est probablement une erreur.

+0

Merci, mais il est assez tard pour répondre :) Il semble que la méthode ci-dessus ne soit pas "la plus" efficace, car il peut y avoir des mouvements inutiles, mais semble tout à fait raisonnable. Puis-je trouver des références sur ce que je devrais faire lorsque des modèles d'expression sont impliqués? Je connais des articles écrits pour C++ 03, mais je n'en ai aucune idée avec C++ 11. Merci encore. –