Wyobraźmy sobie projekt, w którym istnieje klasa interfejs jak poniżej:Dlaczego vtable nie może zawierać duplikatów funkcji?
struct Interface
{
virtual void f()=0;
virtual void g()=0;
virtual void h()=0;
};
Załóżmy, że gdzieś indziej, ktoś chce utworzyć klasę wykonawczą tego interfejsu, dla którego f
, g
, h
wszystkim zrobić to samo .
struct S : Interface
{
virtual void f() {}
virtual void g() {f();}
virtual void h() {f();}
};
Wtedy byłby to ważny optymalizacji w celu wygenerowania vtable dla S
którego wpisy są wszystkie wskaźniki S::f
, oszczędzając w ten sposób wywołanie funkcji owijania g
i h
.
Drukowanie zawartości vtable pokazuje jednak, że ta optymalizacja nie jest wykonywana:
S s;
void **vtable = *(void***)(&s); /* I'm sorry. */
for (int i = 0; i < 3; i++)
std::cout << vtable[i] << '\n';
0x400940
0x400950
0x400970
Kompilacja z -O3
lub -Os
nie ma efekt, podobnie jak przełączanie między klangiem i gcc.
Dlaczego ta możliwość optymalizacji została pominięta?
W chwili obecnej są to przypuszczenia, że mam uznawane (i odrzucone):
- vtable kod druk rzeczywiście drukuje śmieci.
- Poprawa wydajności uważana jest za bezwartościową.
- ABI to zabrania.
Optymalizacja ta będzie widoczna dla kodu zgodne, ponieważ wskaźniki do funkcji składowych byłoby porównać równe. –
Może wydawać się naiwny, ale dla mnie * funkcja nazywająca 'f' * nie jest' f' sama. Byłoby więc dziwnie, gdyby wskaźniki do funkcji członków były równe, nie sądzisz? –
@David Schwartz: llvm jest znany z tego, że może wykonywać takie czynności, jak kod inline za pomocą wskaźników funkcji. przypuszczalnie może również inline ciała 'f' w' G' i 'h' również? To nie jest to samo, co optymalizacja zaproponowana przez OP. Zgaduję, że ta optymalizacja nie jest w praktyce bardzo ważna, więc nikt się nie przejmuje? Czuje się jak „wskaźnik do funkcji członka-” porównującego równe problem mógł być albo wykrywane przez kompilator lub średnia może być modyfikowana w celu umożliwienia funkcji optymalizacji Anyways w ten sam sposób, że kopiowanie ellision jest dozwolone –