Le compilateur est-il autorisé à optimiser les membres de données privées?

Dec 08 2020

Si le compilateur peut prouver qu'un membre (privé) d'une classe n'est jamais utilisé, y compris par des amis potentiels, le standard permet-il au compilateur de supprimer ce membre de l'empreinte mémoire de la classe?

Il va de soi que cela n'est pas possible pour les membres protégés ou publics au moment de la compilation, mais il peut y avoir des circonstances dans lesquelles il est possible, concernant des données privées membres, qu'une telle preuve soit construite.


Questions connexes:

  • Dans les coulisses du public, privé et protégé (a déclenché cette question)
  • Le compilateur C ++ est-il autorisé à optimiser les objets locaux non référencés (à propos des objets automatiques)
  • Une variable statique utilisera-t-elle toujours de la mémoire? (à propos des objets statiques)

Réponses

31 PeterCordes Dec 08 2020 at 23:19

Possible en théorie (avec les membres publics inutilisés), mais pas avec le type d'écosystème de compilateur auquel nous sommes habitués (ciblant une ABI fixe qui peut lier du code compilé séparément). La suppression des membres inutilisés ne peut être effectuée qu'avec une optimisation de l'ensemble du programme qui interdit les bibliothèques séparées 1 .

D'autres unités de compilation devront peut-être s'entendre sizeof(foo), mais ce ne serait pas quelque chose que vous pourriez dériver .hsi cela dépendait de la vérification qu'aucune implémentation du comportement d'une fonction membre ne dépendait de membres privés.

N'oubliez pas que C ++ ne spécifie vraiment qu'un seul programme, pas un moyen de créer des bibliothèques. Le langage spécifié par ISO C ++ est compatible avec le style d'implémentation auquel nous sommes habitués (bien sûr), mais des implémentations qui prennent tous les fichiers .cppet .hà la fois et produisent un seul exécutable autonome non extensible sont possibles.

Si vous contraignez suffisamment l'implémentation (pas d'ABI fixe), une application agressive de la règle as-if pour l'ensemble du programme devient possible.


Note de bas de page 1: J'allais ajouter " ou exporter les informations de taille d'une manière ou d'une autre vers un autre code en cours de compilation " comme moyen d'autoriser les bibliothèques, si le compilateur pouvait déjà voir les définitions pour chaque fonction membre déclarée dans la classe. Mais la réponse de @ PasserBy souligne qu'une bibliothèque compilée séparément pourrait être la chose qui utilise les membres privés déclarés de manière à produire finalement des effets secondaires visibles de l'extérieur (comme les E / S). Il faudrait donc les exclure complètement.

Étant donné que, les membres publics et privés sont équivalents aux fins d'une telle optimisation.

17 KonradRudolph Dec 08 2020 at 22:26

Si le compilateur peut prouver qu'un membre (privé) d'une classe n'est jamais utilisé

Le compilateur ne peut pas le prouver, car les membres privés peuvent être utilisés dans d'autres unités de compilation. Concrètement, cela est possible dans le contexte d'un pointeur vers un membre dans un argument modèle selon [temp.spec] / 6 du standard, comme décrit à l'origine par Johannes Schaub .

Donc, en résumé: non, le compilateur ne doit pas optimiser les membres de données privées, pas plus que les membres publics ou protégés (sous réserve de la règle as-if).

11 PasserBy Dec 08 2020 at 22:30

Non, car vous pouvez renverser légalement le système de contrôle d'accès .

class A
{
    int x;
};

auto f();

template<auto x>
struct cheat
{
    friend auto f() { return x; }
};

template struct cheat<&A::x>;  // see [temp.spec]/6

int& foo(A& a)
{
    return a.*f();  // returns a.x
}

Étant donné que le compilateur doit corriger l'ABI lors de sa Apremière utilisation et qu'il ne peut jamais savoir si un futur code pourra y accéder x, il doit réparer la mémoire de Apour contenir x.