Est-il des cas où une classe virtuelle et déclare des méthodes que le compilateur n'a pas besoin d'utiliser un VPTR?

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

  •  22-09-2019
  •  | 
  •  

Question

Je me demandais s'il y a une optimisation possible où le compilateur n'a pas besoin d'attribuer un VPTR à un objet instancié même si le type de l'objet est une classe avec des méthodes virtuelles.

Par exemple, considérons:

#include <iostream>
struct FooBase
{
  virtual void bar()=0;
};

struct FooDerived : public FooBase
{
  virtual void bar() { std::cout << "FooDerived::bar()\n"; }
};

int main()
{
   FooBase* pFoo = new FooDerived();
   pFoo->bar();

  return 0;
}

Dans cet exemple, le compilateur sait sûrement ce sera le type de pFoo au moment de la compilation, donc il n'a pas besoin d'utiliser un VPTR pour pFoo, non? Y at-il des cas plus intéressants où le compilateur peut éviter d'utiliser un VPTR?

Était-ce utile?

La solution

Miser sur réponse d'Andrew Stein , parce que je pense que vous voulez aussi savoir quand le soi-disant « frais généraux d'exécution des fonctions virtuelles » peut être évité. (Les frais généraux est là, mais il est petit , et rarement la peine se soucier.)

Il est vraiment difficile d'éviter les Espace du pointeur vtable, mais le pointeur lui-même peut être ignorée, y compris dans votre exemple. Parce que pFoo initialisation de est dans ce cadre, le compilateur sait que pFoo->bar doit vouloir dire FooDerived de bar , et n'a pas besoin de vérifier la vtable. Il y a aussi plusieurs techniques de mise en cache pour éviter de multiples recherches de vtable, allant du simple au complexe.

Autres conseils

Même dans le cas où vous montrer, je doute que tout compilateur fera ce que vous suggérez.

Vous utilisez un programme très simple en un seul fichier.

Imaginez que vous avez FooBase et FooDerived dans .h et foo.cpp et principal main.cpp. Lors de la compilation foo.cpp, comment est le compilateur de savoir que tout le programme il n'y a pas besoin d'un vtbl. Il n'a pas vu main.cpp.

La décision finale ne peut être faite au moment de la liaison, quand il est trop tard et compliqué de modifier le fichier objet, trouver tous les appels à sizeof (FooDerived), etc.

Même les plus modernes, les compilateurs mondialement collent encore l'optimisation du principe de la « traduction indépendante ». Selon ce principe, chaque unité de traduction est compilé de manière indépendante, sans aucune connaissance des autres unités de traduction qui pourraient exister dans l'ensemble du programme final.

Lorsque vous déclarez une classe avec lien externe, cette classe peut être utilisé dans d'autres unités de traduction. Le compilateur n'a aucune idée sur la façon dont pourrait être utilisé votre classe dans les autres unités de traduction. Ainsi, il doit supposer que tous les cas de cette force de classe en général besoin de son pointeur de table virtuelle initialisé correctement au moment de la construction.

Dans votre exemple un compilateur intelligent peut comprendre que le type dynamique de l'objet *pFoo est FooDerived. Cela permettrait au compilateur d'optimiser le code: pour générer un appel direct à FooDerived::bar fonction en réponse à pFoo->bar() expression (sans utiliser la table virtuelle). Mais néanmoins, le compilateur aurait normalement encore pour initialiser correctement le pointeur de la table virtuelle dans chaque objet FooDerived.

Il est possible pour un compilateur de couper la tête de indirection de la fonction virtuelle des appels quand il sait que la méthode de la classe exacte va être invoquée. Ceci est le résultat d'une forme de Points à analyse compilateurs optimisation font. Ils tracent le flux de données de variables de pointeur, et en tout lieu d'un pointeur ne peut pointer vers des objets d'un type, il peut générer des appels pour exactement ce type, la mise en œuvre de manière statique sémantique d'appels virtuels (à savoir au moment de la compilation).

Comme beaucoup d'autres l'ont dit, à moins que le compilateur fait optimisation tout le programme / link-temps (de plus en plus populaire, gagne du CCG en 4.5), il a encore besoin de générer une sorte de table des fonctions virtuelles pour soutenir la compilation séparée .

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