Question

Si une fonction renvoie un objet, mais que cette valeur de retour n'est jamais utilisée par l'appelant, le compilateur optimisera-t-il la copie? (Peut-être une réponse toujours / parfois / jamais.)

Exemple élémentaire:

ReturnValue MyClass::FunctionThatAltersMembersAndNeverFails()
{
    //Do stuff to members of MyClass that never fails
    return successfulResultObject;
}

void MyClass::DoWork()
{
    // Do some stuff
    FunctionThatAltersMembersAndNeverFails();
    // Do more stuff
}

Dans ce cas, l'objet ReturnValue sera-t-il copié? Est-ce même construit? (Je sais que cela dépend probablement du compilateur, mais limitons cette discussion aux plus populaires.)

EDIT: Simplifions cela un peu, car il ne semble pas y avoir de consensus dans le cas général. Que se passe-t-il si ReturnValue est un entier et que nous renvoyons 0 au lieu de successfulResultObject ?

Était-ce utile?

La solution

Si la classe ReturnValue a un constructeur de copie non trivial, le compilateur ne doit pas éliminer l'appel du constructeur de copie - il est requis par le langage dans lequel elle est invoquée.

Si le constructeur de la copie est inline, le compilateur pourrait peut-être insérer l'appel, ce qui pourrait alors entraîner l'élimination d'une grande partie de son code (également selon que FunctionThatAltersMembersAndNeverFails est inline ou non).

Autres conseils

Ils le feront probablement si le niveau d'optimisation les amène à intégrer le code. Sinon, ils devront générer deux traductions différentes du même code pour le faire fonctionner, ce qui pourrait poser de nombreux problèmes.

L’éditeur de liens peut s’occuper de ce genre de chose, même si l’appelant initial et appelé sont dans des unités de compilation différentes.

Si vous avez une bonne raison de vous inquiéter à propos de la charge de l'UC dédiée à un appel de méthode (l'optimisation prématurée est la racine de tout mal,), vous pouvez envisager les nombreuses options en ligne à votre disposition, y compris (gasp!) .

Avez-vous VRAIMENT besoin d'optimiser à ce niveau?

Si la valeur renvoyée est un int et que vous renvoyez 0 (comme dans la question modifiée), cela peut être optimisé.

Vous devez regarder l'assemblage sous-jacent. Si la fonction n'est pas en ligne, l’assemblage sous-jacent exécutera un mov eax, 0 (ou xor eax, eax) pour définir eax (qui est généralement utilisé pour les valeurs de retour entières) sur 0. Si la fonction est en ligne, elle obtiendra certainement optimisé loin.

Mais ce scénario n’est pas très utile si vous vous inquiétez de ce qui se passe lorsque vous renvoyez des objets de plus de 32 bits. Vous devrez vous reporter aux réponses à la question unedit, qui brossent un assez bon tableau: si tout est en ligne, la majeure partie sera optimisée. Si ce n'est pas en ligne, alors les fonctions doivent être appelées même si elles ne font vraiment rien, et cela inclut le constructeur d'un objet (puisque le compilateur ne sait pas si le constructeur a modifié des variables globales ou fait autre chose de bizarre) .

Je doute que la plupart des compilateurs puissent le faire s’ils se trouvaient dans différents objets de compilation (fichiers différents). Peut-être que s'ils étaient tous deux dans le même fichier, ils le pourraient.

Il y a de bonnes chances qu'un optimiseur de judas détecte ce problème. De nombreux compilateurs (la plupart?) En implémentent un, la réponse est donc probablement "oui".

Comme d’autres notent, ce n’est pas une question triviale au niveau de la réécriture AST.

Les optimiseurs Peephole travaillent sur une représentation du code à un niveau équivalent au langage assembleur (mais avant la génération du code machine réel). Il est possible de remarquer le chargement de la valeur de retour dans un registre suivi d'un écrasement sans lecture intermédiaire et de simplement supprimer le chargement. Cela se fait au cas par cas.

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