Quelle est la meilleure signature pour les opérateurs arithmétiques surchargés en C ++?

StackOverflow https://stackoverflow.com/questions/118630

  •  02-07-2019
  •  | 
  •  

Question

J'avais supposé que la forme canonique de l'opérateur +, supposant l'existence d'un opérateur surchargé + = fonction membre, était comme ceci:

const T operator+(const T& lhs, const T& rhs)
{
    return T(lhs) +=rhs;
}

Mais on m'a fait remarquer que cela fonctionnerait aussi:

const T operator+ (T lhs, const T& rhs)
{
    return lhs+=rhs;
}

En substance, ce formulaire transfère la création du temporaire du corps de l'implémentation à l'appel de fonction.

Il semble un peu gênant d’avoir des types différents pour les deux paramètres, mais y at-il un problème avec la deuxième forme? Y a-t-il une raison de préférer l'une à l'autre?

Était-ce utile?

La solution

Avec la question modifiée, le premier formulaire serait préféré. Le compilateur optimisera probablement la valeur de retour (vous pouvez le vérifier en plaçant un point d'arrêt dans le constructeur de T). La première forme prend également les deux paramètres comme const, ce qui serait plus souhaitable.

Recherche sur le thème de l'optimisation des valeurs de retour , tel que ce lien, par exemple: http://www.cs.cmu.edu/~gilpin/c++/performance.html

Autres conseils

Je ne suis pas sûr qu'il y ait beaucoup de différence dans le code généré pour l'un ou l'autre.

Entre ces deux, je préférerais (personnellement) la première forme, car elle traduit mieux l’intention. Ceci concerne à la fois votre réutilisation de l’opérateur + = et l’idée de passer des types modélisés par const & amp..

Je préférerais que le premier formulaire soit lisible.

J'ai dû réfléchir à deux fois avant de voir que le premier paramètre était copié. Je ne m'y attendais pas. Par conséquent, étant donné que les deux versions sont probablement aussi efficaces, je choisirais une version plus facile à lire.

const T operator+(const T& lhs, const T& rhs)
{
    return T(lhs)+=rhs;
}

pourquoi pas cela si vous voulez la concision?

Ma première pensée est que la deuxième version pourrait être infiniment plus rapide que la première, car aucune référence n’est poussée sur la pile en tant qu’argument. Cependant, cela dépendrait beaucoup du compilateur et dépendrait par exemple du fait que le compilateur optimise ou non l'optimisation de la valeur de retour.

Quoi qu’il en soit, en cas de doute, ne choisissez jamais un gain de performance minime qui pourrait même ne pas exister et dont vous n’auriez probablement pas besoin - choisissez la version la plus claire, qui est la première.

En fait, la seconde est préférable. Comme indiqué dans la norme c ++,

  

3.7.2 / 2: Durée de stockage automatique

     

Si un objet automatique nommé a   initialisation ou un destructeur avec   effets secondaires, il ne doit pas être   détruit avant la fin de son bloc,   il ne sera pas non plus éliminé en tant que   optimisation même s'il semble être   non utilisé, sauf qu'un objet de classe ou   sa copie peut être éliminée comme   spécifié en 12.8.

En effet, comme un objet temporaire sans nom est créé à l'aide d'un constructeur de copie, le compilateur ne peut pas utiliser l'optimisation de la valeur de retour. Dans le second cas, toutefois, l'optimisation de la valeur de retour sans nom est autorisée. Notez que si votre compilateur implémente l'optimisation des valeurs de retour nommées, le meilleur code est

.
const T operator+(const T& lhs, const T& rhs)
{
    T temp(lhs);
    temp +=rhs;
    return temp;
}

Je pense que si vous les intégriez tous les deux (comme je le ferais, étant donné qu'ils ne font que transférer des fonctions et que la fonction operator + = () est probablement hors ligne), vous obtiendrez une génération de code presque indiscernable. Cela dit, le premier est plus canonique. La deuxième version est inutilement "mignonne".

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top