37 votes

Les compilateurs C ++ modernes sont-ils en mesure d’éviter d’appeler une fonction const deux fois dans certaines conditions?

Par exemple, si j'ai ce code:

class SomeDataProcessor
{
public:
    bool calc(const SomeData & d1, const SomeData & d2) const;
private:
    //Some non-mutable, non-static member variables
}

SomeDataProcessor sdp;
SomeData data1;
SomeData data2;

someObscureFunction(sdp.calc(data1, data2),
                    sdp.calc(data1, data2));

Prenons comme potentiellement équivalent de code:

bool b = sdp.calc(data1, data2);
someObscureFunction(b,b);

Pour que cela soit valide, l' calc() fonction doit répondre à certaines exigences, et pour l'exemple que j'appel la propriété _pure_const_formula_

Un _pure_const_formula_ serait:

  • Pas de changement de tout membre, statique ou variable globale de l'état
  • Appel seulement _pure_const_formula_ fonctions
  • Peut-être que certaines autres conditions que je n'ai pas à l'esprit

Par exemple, l'appel d'un générateur de nombre aléatoire ne répondrait pas à ces exigences.

Est le compilateur a permis de remplacer le premier code avec le second, même si elle a besoin de creuser récursivement les fonctions dites? Sont les compilateurs modernes capable de faire cela?

46voto

Tamás Zahola Points 1352

GCC a l' pure d'attribut (comme __attribute__((pure))) pour les fonctions qui indique au compilateur que les appels redondants peuvent être éliminés. Il est utilisé par exemple sur strlen.

Je ne suis pas au courant de tout compilateur de faire cela automatiquement, surtout compte tenu du fait que l'exercice de la fonction appelée peut ne pas être disponible sous forme de code source, et l'objet de formats de fichiers contiennent aucune métadonnée de savoir si une fonction est pur ou non.

22voto

Oui, absolument.

Les compilateurs de le faire tout le temps, et plus.

Par exemple, si votre fonction ne furent de retour true, et sa définition ont été visibles par le compilateur à la callsite, l'intégralité de la fonction d'appel serait probablement être gommés, ayant pour résultat juste:

someObscureFunction(true, true);

Un programme pour lequel le compilateur dispose de suffisamment d'informations peuvent être "optimisé" à partir d'un très complexe de la chaîne de tâches en bas à peut-être une ou deux instructions. Maintenant, effectivement d'exploitation sur les variables de membre est de pousser l'optimiseur de sa limite dans une certaine mesure, mais si les variables sont private, sont connus valeur initiale, et ne sont pas muté par tout autre membre de la fonction, je ne vois pas pourquoi un compilateur ne pouvait pas juste inline sa valeur connue si elle le voulait. Les compilateurs sont très, très intelligent.

Les gens pensent qu'un programme compilé est un one-to-one mapping de lignes dans votre code source, mais ce n'est presque jamais vrai. Le but entier de C++, c'est que c'est une abstraction de ce que votre ordinateur est en fait va être fait lors de l'exécution de votre programme.

10voto

Sam Varshavchik Points 2563

Non, étant donné le code, le compilateur ne peut pas garantir que le projet d'optimisation aura pas de différences observables, et pas moderne compilateur sera en mesure d'optimiser loin le deuxième appel de fonction.

Un exemple très simple: cette méthode de classe peut utiliser un générateur de nombre aléatoire, et enregistrer le résultat dans un tampon, qu'une autre partie du code se lit plus tard. Évidemment, l'élimination d'un appel de fonction maintenant les résultats dans moins de généré de façon aléatoire les valeurs placée dans un tampon.

En d'autres termes, tout simplement parce que d'une méthode de classe est - const ne signifie pas qu'il n'a pas observable effets secondaires lorsqu'il est appelé.

4voto

Axel Points 6352

Non, le compilateur n'est pas autorisé à faire cela dans ce cas. Les const signifient uniquement que vous ne modifiez pas l'état de l'objet auquel la méthode appartient. Toutefois, l'appel de cette méthode plusieurs fois avec les mêmes paramètres d'entrée peut donner des résultats différents. Par exemple, pensez à une méthode qui produit un résultat aléatoire.

1voto

BeeOnRope Points 3617

Oui, moderne compilateurs C peut éluder redondant appels de fonction si et seulement si elles peuvent prouver que cette optimisation se comporte comme si, à l'origine sémantique du programme ont été suivies. Par exemple, cela signifie que signifie qu'ils pourraient éliminer les multiples appels à la même fonction avec les mêmes arguments, si la fonction n'a pas d'effets secondaires et si sa valeur de retour ne dépend que de l'argumentation.

Maintenant, vous avez demandé spécifiquement const - c'est surtout utile pour le développeur, et de ne pas le coder. Un const fonction est une des astuces que la méthode ne modifie pas l'objet auquel il est appelé, et const arguments sont des conseils que les arguments ne sont pas modifiés. Toutefois, la fonction peut (légalement1) a jeté l' const-ness de l' this de pointeur ou de ses arguments. Ainsi, le compilateur ne peut pas compter sur elle.

En outre, même si const objets passés à une fonction vraiment n'ont jamais été modifiés à l'intérieur de cette fonction, et const fonctions jamais modifié le récepteur de l'objet, la méthode peut facilement compter sur mutable données globales (et peut muter ces données). Considérons, par exemple, une fonction qui renvoie l'heure actuelle, ou qui incrémente un compteur global.

Si l' const déclarations aider le programmeur, pas le compilateur2.

Cependant, le compilateur peut-être utiliser d'autres astuces pour prouver les appels sont redondants:

  • La fonction peut être dans la même unité de compilation en tant qu'appelant, permettant au compilateur de l'inspecter et de déterminer exactement de quoi elle repose. La forme ultime de ce qui est l'in-lining: le corps de la fonction peut être déplacé en l'appelant à quel point l'optimiseur peut supprimer code redondant de plus tard appels (jusqu'à y compris tout le code à partir de ces appels entièrement et peut-être toutes ou le port de l'appel d'origine aussi).
  • La suite d'outils peut utiliser un certain type de lien temps-optimisation, qui permet effectivement le type d'analyse décrit dans le point ci-dessus, même pour les fonctions et les appelants dans les différentes unités de compilation. Cela pourrait permettre cette optimisation pour tout le code présent lors de la finale de l'exécutable est généré.
  • Le compilateur peut permettre à l'utilisateur d'annoter une fonction avec un attribut qui informe le compilateur que l'on peut considérer la fonction comme n'ayant pas d'effets secondaires. Par exemple, gcc fournit l' pure et const fonction des attributs qui informe gcc que les fonctions n'a pas d'effets secondaires, et ne dépendent que de leurs paramètres (et sur des variables globales, dans le cas d' pure).

1 Généralement, tant que l'objet n'a pas été défini à l'origine comme const.

2 Il est en un certain sens, const définitions ne l'aide du compilateur: ils peuvent mettre des objets globaux définis comme const en lecture seule section de l'exécutable (si une telle fonction existe) et également combiner ces objets lorsqu'ils sont égaux (par exemple, à l'identique des constantes de chaîne).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X