Sind Vererbungskosten relativ dazu, ob Objekte auf dem Stack oder Heap zugeordnet sind?

8

Betrachten Sie das folgende Setup.

%Vor%

Damit kann ich eine Funktion wie die folgende schreiben.

%Vor%

In dieser Situation zahle ich einige Kosten für die Vererbung und den Polymorphismus, nämlich eine vtable und Aufrufe an F können nicht inline sein, wenn sie wie folgt verwendet werden (korrigiert mich, wenn ich falsch liege).

%Vor%

Was ich wissen möchte, ist, ob ich dieselben Kosten bezahlen muss, wenn ich A oder B als Objekte verwende, die auf dem Stack zugewiesen sind, wie im folgenden Code.

%Vor%

Haben A und B Vtables, wenn sie auf dem Stack zugewiesen sind? Kann der Aufruf von F inline sein?

Es scheint mir, dass ein Compiler möglicherweise zwei Speicherlayouts für Klassen in einer Vererbungshierarchie erstellen könnte - eine für den Stack und eine für den Heap. Wird ein C ++ - Compiler dies tun / tun? Oder gibt es einen theoretischen oder praktischen Grund, warum das nicht möglich ist?

Bearbeiten:

Ich habe einen Kommentar gesehen (der aussieht, als wäre er gestrichen), der tatsächlich einen guten Punkt angesprochen hat. Sie könnten immer Folgendes tun, und dann wäre% c1_de%, das auf dem Stapel zugewiesen wurde, möglicherweise nicht der hervorstechende Punkt, an dem ich versuche, zu erhalten ...

%Vor%

Vielleicht wäre es eine bessere Art, es zu formulieren: "Ist das Verhalten für ein Objekt anders, das auf dem Stapel zugeordnet ist und wird als 'normaler Werttyp' verwendet?" Bitte helfen Sie mir hier mit der Terminologie, wenn Sie wissen, was ich meine, aber eine bessere Art, es zu sagen!

Der Punkt, an dem ich versuche, ist, dass Sie die Definition der Basisklasse zur Kompilierungszeit in die abgeleitete Klasse, in der Sie eine Instanz auf dem Stapel zuweisen, praktisch "abflachen" könnten.

    
Timothy Shields 17.05.2013, 22:15
quelle

2 Antworten

7

Ich denke, Ihre Frage hat wirklich damit zu tun, ob ein Compiler statisches Wissen über ein Objekt hat und der Vtable-Lookup (Sie haben dies bei Ihrer Editierung erwähnt) statt einer Unterscheidung, wo das Objekt lebt - Stack oder Haufen. Ja, viele Compiler können in diesem Fall den virtuellen Versand blockieren.

    
Scott Jones 17.05.2013, 22:31
quelle
1

Die Bearbeitung Ihrer Frage fragt, ob Sie die Definition der Basisklasse A in die abgeleitete Klasse B reduzieren können. Wenn der Compiler zur Kompilierzeit feststellen kann, dass ein Objekt immer nur eine Instanz von B enthält, kann er die vtable-Suche zur Laufzeit eliminieren und B.F(); für diesen bestimmten Aufruf aufrufen.

Zum Beispiel wird der Compiler wahrscheinlich die vtable-Suche zur Laufzeit unten eliminieren und die abgeleitete Funktion aufrufen:

%Vor%

Im folgenden Code wird der Compiler nicht in der Lage sein, die Laufzeit-Suche in doSomething zu eliminieren, aber wahrscheinlich kann die Suche in b.F()

eliminieren %Vor%

Beachten Sie, ob das Objekt auf dem Stapel oder dem Heap zugeordnet ist. Entscheidend ist, dass der Compiler den Typ bestimmen kann. Jede Klasse hat immer noch eine V-Tabelle, sie wird möglicherweise nicht immer für jeden Methodenaufruf benötigt.

Sie erwähnen Code-Inlining, dies hängt nicht damit zusammen, wie das Objekt zugewiesen wird. Wenn eine normale Funktion aufgerufen wird, werden Variablen zusammen mit einer Rücksprungadresse auf den Stapel geschoben. Die CPU springt dann zur Funktion. Mit Inline-Code wird der Standort des Funktionsaufrufs durch den tatsächlichen Code ersetzt (ähnlich einem Makro).

Wenn ein Objekt, das in einer Vererbungshierarchie enthalten ist, auf dem Stapel zugeordnet ist, muss der Compiler noch in der Lage sein zu bestimmen, welche Funktionen es aufrufen kann, insbesondere wenn es virtuelle und nicht-virtuelle Funktionen gibt.

    
Steve 17.05.2013 22:32
quelle

Tags und Links