variable in for-Schleife deklarieren
-
Fuer folgende Schleife:
for(classIterator = classList.begin(); i!=classList.end(); classIterator++){ AnyClass *classPointer = *classIterator; //... irgendwelcher code }Macht es einen performance (oder sonstigen) Unterschied "classPointer" ausserhalb der for Schleife zu deklarieren?
Vielen Dank,
Ali
-
Wenn dann nur einen geringen.
Du erzeugst ja nicht jedes Mal eine neue Instanz, sondern eben nur einen Pointer.
Aber dieser Pointer wird jedes Mal neu angelegt.
Also >> vor die Schleife << .
-
Ich würde sagen, dass es hier völlig sinnlos ist, da du mit dem Iterator schon eine Art Zeiger hast. Die Zuweisung sollte dann auch so aussehen, wenn es ein Zeiger sein muss:
AnyClass *classPointer = &*classIterator;Ansonsten definiere ich Variablen so lokal wie möglich, es sei denn der Profiler legt mir was anderes nahe. Das kommt aber ausgesprochen selten vor.
-
Syntaktisch / semantisch macht es sehr wohl einen Unterschied, da die Variable danach sichtbar bleibt. Dann kannst Du sie z.B. aus Versehen danach nochmal benutzen, auch wenn sie keinen sinnvollen Wert mehr enthält.
Performance sollte dir hier lieber egal sein. Du kannst dich darauf verlassen, dass dein Compiler dir das schon gut optimiert.
Zu deiner Beruhigung
:
Zu 99,99% wird die Variable vom Compiler nur ein einziges Mal angelegt und für jeden Schleifendurchlauf überschrieben. Schwieriger wird's hier nur, wenn das Objekt einen nicht trivialen Konstruktor/Destruktor hat. Erst in diesem Falle sollte man überhaut über einen Performance-Gewinn nachdenken.
-
Der Einfluss auf die Performance haengt davon ab, wie oft die Schleife durchlaufen wird. Wenn Dir den Kram mal im Assmebler anschaust, wirst Du sehen, dass PUSH und POP Befehle beim jedem Aufruf der Schleife fuer die diese Variable benutzt werden. D. h. es gibt Zugriffe auf den Stack bei jedem Durchlauf. Wenn Du unbedingt vermeiden willst, dass der Pointer classPointer jedesmal neu aufgebaut wird und auch nicht in der gesammten Funktion/Methode sichbar ist (aus den o.g. Gruenden) gibt es folgende Klempnerei:
{ AnyClass *classPointer = *classIterator; for(classIterator = classList.begin(); i!=classList.end(); classIterator++) { //... irgendwelcher code } } // ab hier ist class Pointer unsichtbarAber schoen ist es nicht.
-
MBCS-CITP schrieb:
Wenn Dir den Kram mal im Assmebler anschaust, wirst Du sehen, dass PUSH und POP Befehle beim jedem Aufruf der Schleife fuer die diese Variable benutzt werden. D. h. es gibt Zugriffe auf den Stack bei jedem Durchlauf.
War das mit oder ohne Optimierungen? Und welcher Compiler? Würde mich schon wundern, wenn ein optimierende Compiler so einen ineffizienten Code generieren würde.
-
Ohne Optimierung. Es ist bei optimierten Code oft sehr schwierig wirklich die entsprechende Stelle zu finden. Aber: Bevor ich mich darauf verlasse, dass der Compiler das schon richten wird, zwinge ich lieber den Compiler das zu tun, was ich will.
-
ich halte es für schlechten stil variablen innerhalb von schleifen zu deklarieren
@7H3 N4C3R wenn man aus versehen auf variablen zugreift sollte man seinen code eh nochmal überdenken

-
MBCS-CITP schrieb:
Ohne Optimierung. Es ist bei optimierten Code oft sehr schwierig wirklich die entsprechende Stelle zu finden. Aber: Bevor ich mich darauf verlasse, dass der Compiler das schon richten wird, zwinge ich lieber den Compiler das zu tun, was ich will.
schlecht. lern lieber moderne compiler kennen. sagen wir mal, ab 1998.
-
Sovok schrieb:
ich halte es für schlechten stil variablen innerhalb von schleifen zu deklarieren
es ist aber in c++ guter stil. bei deinem c war das noch anders, aber die zeiten sind um.
-
MBCS-CITP schrieb:
Bevor ich mich darauf verlasse, dass der Compiler das schon richten wird, zwinge ich lieber den Compiler das zu tun, was ich will.
dein compiler ist ne dampfmaschine und du optimierst das falsche.
in der tat isses so, daß das push/pop gar nicht passiert, sondern daß er für sowas mickriges ein register nimmt.
man sollte dem compiler die möglichkeit geben, so oft wie möglich register zu benutzen. und vor allem, die register auch wegschmeißen zu können, ohne den wert in ne stack-variable zurückspeichern zu müssen.
deswegen mußt du die varialen schlicht so lokal wie mmöglich machen, um dem optimierer sein spiel zu erleichtern. der kann grundsätzlich ohne nachzudenken und ohne performanceverlust, lokale variablen auch ein wenig globaler machen. er kann aber nicht grundsätzlich globale variablen lokaler machen.
-
MBCS-CITP schrieb:
Ohne Optimierung. Es ist bei optimierten Code oft sehr schwierig wirklich die entsprechende Stelle zu finden. Aber: Bevor ich mich darauf verlasse, dass der Compiler das schon richten wird, zwinge ich lieber den Compiler das zu tun, was ich will.
Dann bringen deine Beobachtungen aber rein gar nichts. Der Unterschied zwischen optimiertem und nicht-optimiertem Code ist so groß, daß man von einem nicht auf den anderen schließen kann. Das ist aus meiner Erfahrung ganz besonders bei Templates der Fall. Und so führen dann Beobachtungen an nicht-optimiertem Code dazu, daß Leute ihren Code selbst mikro-optimieren (und somit in der Regel schlecht wartbar machen), ohne daß es bei zugeschalteten Optimierungen etwas ausmachen würde
-
profiler arbeiten imho in der regel auch mit optimiertem code
-
Man lernt nie, ich habe etwas herumgespielt (gcc 4.01 auf Linux). Es ist tatsaechlich so, dass ein einzelner Pointer nur im Register verwaltet wird, waehrend ein String aus 10 chars in den Stack geschoben wird.
Nun ich habe noch gelernt, dass saemtliche locale Variablen in Stack geschrieben werden. Ist wohl nicht mehr up-to-date.
-
Nun ich habe noch gelernt, dass saemtliche locale Variablen in Stack geschrieben werden. Ist wohl nicht mehr up-to-date.
Je nach Optimierungsqualität bleiben einige Variablen auch im Register, oder sie "wandern" zwischen Registern und Stack hin- und her. So wie es halt gerade am meisten Sinn macht.
Bei den momentaten CPU-Designs muß so vieles beachtet werden, daß ein Mensch das fast nicht mehr hinbekommt, und in den meisten Fällen ein gut angepaßter Compiler (z.B. der Intel-Compiler für x86) das meist besser optimiert. Über so kleine Details wie temporäre Variablen oder ob man eine Variable jetzt einen Scope weiter innen oder außen deklariert, sollte man sich keine Gedanken machen. Der Compiler analysiert den Datenfluß und wird dann meist in beiden Fällen gleich guten Code generieren.
-
MBCS-CITP schrieb:
Nun ich habe noch gelernt, dass saemtliche locale Variablen in Stack geschrieben werden. Ist wohl nicht mehr up-to-date.
was du in schule oder hochschule <edit>in grundlagenfächern</edit> lernst, ist normalerweise 10-15 jahte alt. auch, wenn der prof nen java-aufkleber auf der stirn hat, der ändert gar nix.
-
RolfS schrieb:
Der Compiler analysiert den Datenfluß und wird dann meist in beiden Fällen gleich guten Code generieren.
ja. das hat zur folge, daß sauberer code schneller code ist. außen kann man manchmal mist bauen, ne "eigentlich uninitialisierte" variable in ne komplexe funktion übergeben.
int i; for(i=0;i<100;++i) s+=i; cin>>i; cout<<i; cout<<s;cin>>i sei nicht inline irgendwie.
der compiler muß dafür sorgen, daß vor cin>>i in i die zahl 100 steht! welch ein unfug.int i; for(i=0;i<100;++i) s+=i; int j; cin>>j; cout<<j; cout<<s;dieser code ist optimiererfreundlich. weil er den wert von i nach der schleife nicht mehr anfasst.
natürlich geht auchfor(int i=0;i<100;++i) s+=i; int j; cin>>j; cout<<j; cout<<s;
-
volkard schrieb:
was du in schule oder hochschule <edit>in grundlagenfächern</edit> lernst, ist normalerweise 10-15 jahte alt. auch, wenn der prof nen java-aufkleber auf der stirn hat, der ändert gar nix.
Off-Topic:
... und bei mir 15 Jahre her! Pascal wurde als hochmoderne Sprache verkauft (kein Stein geworfen gegen Pascal, aber dese Aussage war schon damals nicht mehr ganz richtig).