<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Moderne Compiler und Optimierung virtueller Member-Funktionen]]></title><description><![CDATA[<p>Hi!</p>
<p>Ich frage mich gerade wie pfiffig aktuelle Compiler dabei sind herauszufinden, ob sie auf Virtual Dispatch verzichten können.<br />
Angenommen ich habe eine baumförmige Vererbungshierarchie mit virtuellen Funktionen:</p>
<pre><code>struct Basis
{
    virtual void f() { ... };
};

struct A : Basis
{
   ...
};

struct B : A
{
   ...
};

struct Blatt1 : B
{
   void f() override { ... };
};

struct Blatt2 : Basis
{
   void f() override { ... };
};
</code></pre>
<p>... wenn ich nun z.B. über <code>Blatt*</code> die funktion <code>f()</code> aufrufe, kann ich dann im Allgemeinen davon ausgehen,<br />
dass der Compiler im generierten Code auf einen vtable-Lookup verzichtet und die <code>Blatt::f()</code> sogar für Inlining heranzieht?<br />
Schließlich sind die Blätter ja bereits &quot;most derived&quot; (gibts dafür eigentlich nen deutschen Audruck?),<br />
und somit müssen statischer und dynamischer Typ zwangsläufig übereinstimmen.</p>
<p>Ich frage das gerade ohne konkretes Problem, lediglich aus allgemeinen Designüberlegungen heraus.<br />
Bei grafischen Sachen hat man oft mit schlanken Operationen auf vielen solcher Objekte zu tun,<br />
wo der virtual-Overhead durchaus einen Unterschied machen kann. Gleichzeitig wäre es jedoch praktisch,<br />
an anderer Stelle, jenseits des &quot;heißen Pfades&quot;, von der Polymorphie profitieren zu können (z.B. via <code>Base*</code> ).<br />
Ich habe mich bisher etwas schwer getan etwas definitives zu recherchieren und wollte mal eure Meinung dazu hören :).</p>
<p>Gruss,<br />
Finnegan</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/333918/moderne-compiler-und-optimierung-virtueller-member-funktionen</link><generator>RSS for Node</generator><lastBuildDate>Sun, 26 Apr 2026 05:28:44 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/333918.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 10 Aug 2015 19:38:21 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Moderne Compiler und Optimierung virtueller Member-Funktionen on Mon, 10 Aug 2015 20:52:38 GMT]]></title><description><![CDATA[<p>Hi!</p>
<p>Ich frage mich gerade wie pfiffig aktuelle Compiler dabei sind herauszufinden, ob sie auf Virtual Dispatch verzichten können.<br />
Angenommen ich habe eine baumförmige Vererbungshierarchie mit virtuellen Funktionen:</p>
<pre><code>struct Basis
{
    virtual void f() { ... };
};

struct A : Basis
{
   ...
};

struct B : A
{
   ...
};

struct Blatt1 : B
{
   void f() override { ... };
};

struct Blatt2 : Basis
{
   void f() override { ... };
};
</code></pre>
<p>... wenn ich nun z.B. über <code>Blatt*</code> die funktion <code>f()</code> aufrufe, kann ich dann im Allgemeinen davon ausgehen,<br />
dass der Compiler im generierten Code auf einen vtable-Lookup verzichtet und die <code>Blatt::f()</code> sogar für Inlining heranzieht?<br />
Schließlich sind die Blätter ja bereits &quot;most derived&quot; (gibts dafür eigentlich nen deutschen Audruck?),<br />
und somit müssen statischer und dynamischer Typ zwangsläufig übereinstimmen.</p>
<p>Ich frage das gerade ohne konkretes Problem, lediglich aus allgemeinen Designüberlegungen heraus.<br />
Bei grafischen Sachen hat man oft mit schlanken Operationen auf vielen solcher Objekte zu tun,<br />
wo der virtual-Overhead durchaus einen Unterschied machen kann. Gleichzeitig wäre es jedoch praktisch,<br />
an anderer Stelle, jenseits des &quot;heißen Pfades&quot;, von der Polymorphie profitieren zu können (z.B. via <code>Base*</code> ).<br />
Ich habe mich bisher etwas schwer getan etwas definitives zu recherchieren und wollte mal eure Meinung dazu hören :).</p>
<p>Gruss,<br />
Finnegan</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2463332</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2463332</guid><dc:creator><![CDATA[Finnegan]]></dc:creator><pubDate>Mon, 10 Aug 2015 20:52:38 GMT</pubDate></item><item><title><![CDATA[Reply to Moderne Compiler und Optimierung virtueller Member-Funktionen on Mon, 10 Aug 2015 19:45:47 GMT]]></title><description><![CDATA[<p>Ich meine irgendwo gelesen zu haben, dass ein VTABLE lookup aus einer assembler instruction besteht, falls dem so ist wuerde ich mich wundern, wenn man auf Compiler Seite Aufwaende betreiben wuerde um den noch einzusparen.</p>
<p>P.S.: Guck mal in deine Mails <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61b.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_tongue"
      title=":P"
      alt="😛"
    /> oder schau mal wieder im TS vorbei.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2463337</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2463337</guid><dc:creator><![CDATA[Ruvi]]></dc:creator><pubDate>Mon, 10 Aug 2015 19:45:47 GMT</pubDate></item><item><title><![CDATA[Reply to Moderne Compiler und Optimierung virtueller Member-Funktionen on Mon, 10 Aug 2015 20:41:40 GMT]]></title><description><![CDATA[<p>Genau diese Frage hatte ich mir letztens auch einmal gestellt.</p>
<p>Sehr guter Link!<br />
<a href="http://hacksoflife.blogspot.de/2007/04/c-objects-part-8-cost-of-virtual.html" rel="nofollow">http://hacksoflife.blogspot.de/2007/04/c-objects-part-8-cost-of-virtual.html</a></p>
<p>Benjamin Supnik schrieb:</p>
<blockquote>
<p>[...]<br />
So a virtual method is <strong>more expensive</strong> than a function pointer, <strong>by one memory indirection</strong>. If you wanted to optimize this out, you'd put function pointers into the object itself, and pay for the decreased memory chaining with larger object size. The vtable is a layer of indirection.<br />
[...]</p>
</blockquote>
<p>Generelle Informationen. Fand ich hilfreich.<br />
<a href="http://stackoverflow.com/questions/18404988/performance-hit-of-vtable-lookup-in-c" rel="nofollow">http://stackoverflow.com/questions/18404988/performance-hit-of-vtable-lookup-in-c</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2463349</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2463349</guid><dc:creator><![CDATA[Onkki]]></dc:creator><pubDate>Mon, 10 Aug 2015 20:41:40 GMT</pubDate></item><item><title><![CDATA[Reply to Moderne Compiler und Optimierung virtueller Member-Funktionen on Mon, 10 Aug 2015 21:06:04 GMT]]></title><description><![CDATA[<p>Das beantwortet alles nicht die ursprüngliche Frage. Und ja, virtuelle Funktionsaufrufe zu optimieren könnte sich schon lohnen, je nachdem, wieviel die Funktion macht könnte der Aufruf teurer sein, als die Funktion.</p>
<p>Ich denke, in den meisten (sinnvollen) Fällen ist es unmöglich, virtuelle Funktionsaufrufe durch statische zu ersetzen.</p>
<p>Base * b;<br />
if (userInput)<br />
b = new A();<br />
else<br />
b = new B();<br />
b-&gt;foo();</p>
<p>Hier kann der Compiler nicht wissen, ob b A oder B sein wird.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2463353</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2463353</guid><dc:creator><![CDATA[Mechanics]]></dc:creator><pubDate>Mon, 10 Aug 2015 21:06:04 GMT</pubDate></item><item><title><![CDATA[Reply to Moderne Compiler und Optimierung virtueller Member-Funktionen on Mon, 10 Aug 2015 21:47:05 GMT]]></title><description><![CDATA[<p>Leider kann ich die Frage ob bzw. wie gut aktuelle C++ Compiler &quot;devirtualization&quot; können auch nicht beantworten.</p>
<p>Allerdings...<br />
Virtuelle Aufrufe möchte man deswegen loswerden, weil man im non-virtual Fall Inlining machen kann. Und durch Inlining kann es sein dass ein grösserer Haufen Code zu nichts oder fast nichts zusammenfällt. z.B. weil beim Aufruf bestimmte Argumente konstant sind.</p>
<p>Bzw. auch der Aufruf von leeren virtuellen Funktionen - der dann mit devirtualization dann ganz entfernt werden kann.</p>
<p>Oder ... manche Compiler brauchen auch noch ein wenig &quot;Bookkeeping&quot; Code in Funktionen die Exceptions werfen können (bzw. wo Unterfunktionen aufgerufen werden die Exceptions werfen können). Mit Inlining kann der Compiler dann oft sehen dass die aufgerufene Funktion eh keine Exceptions werfen kann, und den entsprechenden Bookkeeping-Code weglassen.</p>
<p>In Summe kann das schätze ich schon ein bisschen was ausmachen. Auf jeden Fall mehr als nur &quot;1 load weniger&quot;.</p>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/28374">@Mechanics</a><br />
Mit Profile guided Optimization kann der Compiler u.U. sehen dass ein virtueller Aufruf an einer bestimmten Stelle zu 70% in Klasse A landet und zu 25% Funktion in Klasse B - und nur zu 5% woanders. Der Compiler könnte dann folgenden Code generieren:</p>
<pre><code class="language-cpp">if (p-&gt;vtable == A::vtable)
{
    // Inline Version von A::Foo
}
else if (p-&gt;vtable == B::vtable)
{
    // Inline Version von B::Foo
}
else
    p-&gt;Foo(args);
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2463361</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2463361</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 10 Aug 2015 21:47:05 GMT</pubDate></item><item><title><![CDATA[Reply to Moderne Compiler und Optimierung virtueller Member-Funktionen on Mon, 10 Aug 2015 22:08:03 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/28374">@Mechanics</a><br />
Mit Profile guided Optimization kann der Compiler u.U. sehen dass ein virtueller Aufruf an einer bestimmten Stelle zu 70% in Klasse A landet und zu 25% Funktion in Klasse B - und nur zu 5% woanders. Der Compiler könnte dann folgenden Code generieren:</p>
<pre><code class="language-cpp">if (p-&gt;vtable == A::vtable)
{
    // Inline Version von A::Foo
}
else if (p-&gt;vtable == B::vtable)
{
    // Inline Version von B::Foo
}
else
    p-&gt;Foo(args);
</code></pre>
</blockquote>
<p>Das wäre interessant... Schon mal ausprobiert, macht der Compiler (VS) sowas tatsächlich? Hab mich noch nie getraut, das mit unserer Software auszuprobieren. Unsere Software ist halt relativ groß... So groß, dass viele Tools oft eh schon aussteigen, z.B. Debugger oder Profiler. Aber für einzelne Dlls und Usecases könnte man das vielleicht tatsächlich mal probieren.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2463366</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2463366</guid><dc:creator><![CDATA[Mechanics]]></dc:creator><pubDate>Mon, 10 Aug 2015 22:08:03 GMT</pubDate></item><item><title><![CDATA[Reply to Moderne Compiler und Optimierung virtueller Member-Funktionen on Mon, 10 Aug 2015 22:50:47 GMT]]></title><description><![CDATA[<p>Zu GCC 5 hab ich folgendes gefunden: <a href="https://gcc.gnu.org/gcc-5/changes.html" rel="nofollow">https://gcc.gnu.org/gcc-5/changes.html</a></p>
<blockquote>
<p>The devirtualization pass was significantly improved by adding better support for speculative devirtualization and dynamic type detection. About 50% of virtual calls in Firefox are now speculatively devirtualized during link-time optimization.</p>
</blockquote>
<p>Zu Visual Studio hab ich folgenden Bug-Report (*g*) gefunden: <a href="https://connect.microsoft.com/VisualStudio/feedback/details/812124/code-gen-bug-incorrect-devirtualization-and-inlining-when-building-with-ltcg" rel="nofollow">https://connect.microsoft.com/VisualStudio/feedback/details/812124/code-gen-bug-incorrect-devirtualization-and-inlining-when-building-with-ltcg</a></p>
<blockquote>
<p>As discussed in <a href="http://www.youtube.com/watch?feature=player_detailpage&amp;v=3MRxucTXPdw#t=2215" rel="nofollow">http://www.youtube.com/watch?feature=player_detailpage&amp;v=3MRxucTXPdw#t=2215</a> the VS 2013 compiler will speculatively devirtualize and inline function calls. (...)</p>
</blockquote>
<p>VS scheint also Devirtualization zu machen. Wie gut ist wieder ne andere Frage <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2463376</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2463376</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 10 Aug 2015 22:50:47 GMT</pubDate></item><item><title><![CDATA[Reply to Moderne Compiler und Optimierung virtueller Member-Funktionen on Mon, 10 Aug 2015 23:57:30 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<p>Zu GCC 5 hab ich folgendes gefunden: <a href="https://gcc.gnu.org/gcc-5/changes.html" rel="nofollow">https://gcc.gnu.org/gcc-5/changes.html</a><br />
...<br />
VS scheint also Devirtualization zu machen. Wie gut ist wieder ne andere Frage <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
</blockquote>
<p>Das klingt auf eden Fall vielversprechend. Wenn das sogar &quot;spekulativ&quot; gemacht wird, sollten besonders offensichtliche Fälle ja gut erkannt werden.<br />
Allerdings bin ich gerade mit meiner ursprünglichen Annahme ans Zweifeln gekommen, dass es bei stärksten abgeleiteten (kann man das so nennen?) Typen eigentlich immer möglich sein sollte, dass der Compiler schon den dynamischen Typen bestimmen kann:<br />
So wie ich das sehe kann der Compiler gar nicht allen Code kennen, in denen die Basisklasse abgeleitet werden könnte. Ich glaube ich habe irgendwann sogar schonmal einer Funktion einer dynamischen Bibliothek einen Basisklassen-Pointer auf eine im Client-Programm abgeleitete Klasse übergeben (bin mir nicht mehr ganz sicher, aber es ist denke ich machbar). In so einem Fall wäre von einem &quot;most derived&quot;-Typen beim kompilieren der Bibliothek auszugehen natürlich keine todsichere Wahl.</p>
<p>Danke jedenfalls bisher für die erhellenden Antworten <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /></p>
<p>Finnegan</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2463387</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2463387</guid><dc:creator><![CDATA[Finnegan]]></dc:creator><pubDate>Mon, 10 Aug 2015 23:57:30 GMT</pubDate></item><item><title><![CDATA[Reply to Moderne Compiler und Optimierung virtueller Member-Funktionen on Tue, 11 Aug 2015 06:23:19 GMT]]></title><description><![CDATA[<p>Dass das ganze wesentlich schlechter funktioniert als z.B. in Java, wo der (JIT-)Compiler es einfach zur Laufzeit machen kann, mit den konkreten Typen die halt wirklich vorkommen, ist klar.<br />
Aber es geht ein bisschen was.<br />
Je nach Programm mehr oder weniger viel.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2463416</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2463416</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 11 Aug 2015 06:23:19 GMT</pubDate></item><item><title><![CDATA[Reply to Moderne Compiler und Optimierung virtueller Member-Funktionen on Tue, 11 Aug 2015 13:07:11 GMT]]></title><description><![CDATA[<p>Bezüglich deiner Orginalfrage, ob virtuelle Memberfunktionen devirtualized werden, wenn Aufruf über Blattklassen stattfindet:<br />
Folgender Code:</p>
<pre><code>struct base
{
  virtual int foo() = 0;
};

struct derived : base
{
	int foo() override {return 1;}
};

int func(derived *ptr)
{
	return ptr-&gt;foo();
}
</code></pre>
<p>Ohne Optimierungen:</p>
<pre><code>func(derived*):
	pushq	%rbp
	movq	%rsp, %rbp
	subq	$16, %rsp
	movq	%rdi, -8(%rbp)
	movq	-8(%rbp), %rax
	movq	(%rax), %rax
	movq	(%rax), %rax
	movq	-8(%rbp), %rdx
	movq	%rdx, %rdi
	call	*%rax
	leave
	ret
</code></pre>
<p>Ich bin kein Assembler Experte, aber das ganze movq Zeugs sieht doch stark nach VTable aus. Quelle: <a href="http://goo.gl/IX6EBX" rel="nofollow">http://goo.gl/IX6EBX</a><br />
Machen wir mal O3 draus:</p>
<pre><code>func(derived*):
	movq	(%rdi), %rax
	movq	(%rax), %rax
	cmpq	derived::foo(), %rax
	jne	.L5
	movl	$1, %eax
	ret
.L5:
	jmp	*%rax
</code></pre>
<p>Wird devirtualized, aber nicht geinlined.<br />
Glücklicherweise gibt es seit C++11 das Keyword final, was dem Compiler mitteilt, dass eine Funktion nicht weiter überschrieben wird, bzw. eine Klasse nicht Basisklasse ist.<br />
Wenden wir das doch mal an, ohne Optimierungen:</p>
<pre><code>func(derived*):
	pushq	%rbp
	movq	%rsp, %rbp
	subq	$16, %rsp
	movq	%rdi, -8(%rbp)
	movq	-8(%rbp), %rax
	movq	%rax, %rdi
	call	derived::foo()
	leave
	ret
</code></pre>
<p>Der Aufruf selber ist ohne VTable und identisch zu der O3 Version, auch ohne Optimierungen (!).<br />
Aktiviert man nun auch noch Optimierungen:</p>
<pre><code>func(derived*):
	movl	$1, %eax
	ret
</code></pre>
<p>Wird geinlined: <a href="http://goo.gl/ukAsll" rel="nofollow">http://goo.gl/ukAsll</a></p>
<p>TL;DR: Nutz final und der Compiler kriegts auf jeden Fall hin.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2463459</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2463459</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Tue, 11 Aug 2015 13:07:11 GMT</pubDate></item><item><title><![CDATA[Reply to Moderne Compiler und Optimierung virtueller Member-Funktionen on Tue, 11 Aug 2015 14:12:09 GMT]]></title><description><![CDATA[<p>Nathan schrieb:</p>
<blockquote>
<p>Machen wir mal O3 draus:</p>
<pre><code>func(derived*):
	movq	(%rdi), %rax
	movq	(%rax), %rax
	cmpq	derived::foo(), %rax
	jne	.L5
	movl	$1, %eax
	ret
.L5:
	jmp	*%rax
</code></pre>
<p>Wird devirtualized, aber nicht geinlined.</p>
</blockquote>
<p>Und wie das geinlined wurde.<br />
Wo siehst du denn einen call?<br />
Ich sehe da nur</p>
<pre><code>jne    .L5                     Jump if Not Equal -&gt; bei L5 geht's weiter wenn doch andere Klasse
                                   Ansonsten:
    movl   $1, %eax                1 nach eax (=Returnwert) kopieren
    ret                            Return
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2463462</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2463462</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 11 Aug 2015 14:12:09 GMT</pubDate></item><item><title><![CDATA[Reply to Moderne Compiler und Optimierung virtueller Member-Funktionen on Tue, 11 Aug 2015 14:23:56 GMT]]></title><description><![CDATA[<p>Nathan schrieb:</p>
<blockquote>
<p>TL;DR: Nutz final und der Compiler kriegts auf jeden Fall hin.</p>
</blockquote>
<p>Hey cool <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /> das <code>final</code> hatte ich ja gar nicht mehr auf dem Radar. Hätte geglaubt dass es dafür nur wenige sinnvolle Anwendungen gibt, aber wenn ich das so sehe kann ich mir sogar vorstellen dass diese Optimierung einer der Hauptgründe dafür war.<br />
Alle Versionen von Clang und GCC, die C++11 unterstützen scheinen das zu inlinen. Wirklich nett. Der Vollständigkeit halber habe ich es hier auch grad nochmal mit Visual C++ (2013) getestet:</p>
<p><em>cl.exe Version 18.00.31101, Full Optimization (/Ox), Inlining: Any Suitable (/Ob2)</em></p>
<pre><code>int func(derived *ptr)
{
    return ptr-&gt;foo();
00007FF66FFF1040 B8 01 00 00 00       mov         eax,1  
}
00007FF66FFF1045 C3                   ret
</code></pre>
<p>Nett ;). Wenn man also <code>final</code> richtig einsetzt, kann man also auch an performancekritischen Stellen virtuelle Funktionen aufrufen (meine Gedanken gehen da z.B. in Richtung massenhafte Kollisions-/Physik-/Partikelobjekte in einem Spieleprojekt), ohne auf Polymorphie-Abstraktion verzichten zu müssen (bzw. umständlich drumherum zu arbeiten). Einziger Overhead ist in dem Fall der Speicher für den vtable-Pointer.</p>
<p>Danke,<br />
Finnegan</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2463463</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2463463</guid><dc:creator><![CDATA[Finnegan]]></dc:creator><pubDate>Tue, 11 Aug 2015 14:23:56 GMT</pubDate></item><item><title><![CDATA[Reply to Moderne Compiler und Optimierung virtueller Member-Funktionen on Tue, 11 Aug 2015 14:39:24 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<pre><code>jne    .L5                     Jump if Not Equal -&gt; bei L5 geht's weiter wenn doch andere Klasse
                                   Ansonsten:
    movl   $1, %eax                1 nach eax (=Returnwert) kopieren
    ret                            Return
</code></pre>
</blockquote>
<p>Ah... ich sehe, da scheinst du ja mit deinem vorherigen Post den richtigen riecher gehabt zu haben:</p>
<p>hustbaer schrieb:</p>
<blockquote>
<pre><code class="language-cpp">if (p-&gt;vtable == A::vtable)
{
    // Inline Version von A::Foo
}
else if (p-&gt;vtable == B::vtable)
{
    // Inline Version von B::Foo
}
else
    p-&gt;Foo(args);
</code></pre>
</blockquote>
<p>Sieht so aus als würden die Compiler tatsächlich auch dann versuchen zu inlinen, wenn der dynamische Typ unbekannt ist. Tippe mal das ist stark von der Komplexität der Vererbungshierarchie abhängig.<br />
Praktisch dass die Compiler so ehrgeizig sind, da kann man sich mehr aufs Programmieren konzentrieren anstatt sich wegen solcher Mikro-Optimierungen nen Kopf zu machen ;).</p>
<p>Finnegan</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2463465</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2463465</guid><dc:creator><![CDATA[Finnegan]]></dc:creator><pubDate>Tue, 11 Aug 2015 14:39:24 GMT</pubDate></item><item><title><![CDATA[Reply to Moderne Compiler und Optimierung virtueller Member-Funktionen on Tue, 11 Aug 2015 18:26:14 GMT]]></title><description><![CDATA[<p>ps: &quot;wenn doch andere Klasse&quot; in meinem Beitrag ist falsch. Er checkt ja direkt den vtable Slot (nicht den vtable Pointer). Er checkt also wirklich die Funktion, nicht die Klasse. Geht also auch mit abgeleiteten Klassen die bloss <code>foo()</code> nicht nochmal überschreiben.<br />
Ein indirekter Load mehr, dafür höhere Trefferwahrscheinlichkeit in vielen Fällen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2463511</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2463511</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 11 Aug 2015 18:26:14 GMT</pubDate></item></channel></rss>