2010-02-12 2 views
8

Haben C++ in einer Weile nicht verwendet. Ich bin auf meinen Java-Compiler angewiesen, um Optimierungen durchzuführen.C++ Deklarieren von int in der for-Schleife

Was ist der am besten optimierte Weg, um eine for-Schleife in C++ zu machen? Oder ist es jetzt gleich mit modernen Compilern? In den "alten Tagen" gab es einen Unterschied.

for (int i=1; i<=100; i++) 

ODER

int i; 
for (i=1; i<=100; i++) 

ODER

int i = 1; 
for (; i<=100; i++) 

Ist es das gleiche in C?

EDIT: Okay, so ist der überwältigende Konsens, den ersten Fall zu verwenden und den Compiler damit zu optimieren, wenn es will.

+6

Diese Art von Frage ist ein wirklich schlechtes Zeichen ... –

+0

+1 Um das zu fragen, nur so kann der Mythos debubed sein – Andres

Antwort

12

Ich würde sagen, dass triviale Dinge wie diese wahrscheinlich vom Compiler optimiert werden, und Sie sollten sich nicht darum kümmern. Die erste Option ist die am besten lesbare, also sollten Sie diese verwenden.

EDIT: Hinzufügen, was andere Antworten sagten, gibt es auch den Unterschied, dass, wenn Sie die Variable in der Schleife initialisieren, wird es aufhören zu existieren, nachdem die Schleife endet.

+2

In Bezug auf Ihre Bearbeitung, hängt dies vom Compiler ab. Ich habe mindestens einen Compiler (MSVC++ 6.0) gesehen, bei dem die Variable nach dem Ende der Schleife nicht mehr existiert. –

+2

@Jeff Normkonforme Compiler beschränken den Geltungsbereich von _i_ auf die for-Schleife, aber es gibt ältere Compiler - wie MSVC++ 6.0 -, die dies nicht tun. Wenn Sie also einen älteren Compiler verwenden, sollten Sie darauf achten. Gemäß dem Sprachstandard ist der Umfang jedoch auf die for-Schleife beschränkt. Neuere Compiler sollten sich in dieser Hinsicht korrekt verhalten. –

+0

Auf MSVC konnte der Hack "#define für if (0) {} else for" verwendet werden, um das richtige Verhalten zu erhalten. Ach ja, die guten alten Tage ... –

4

Es ist das gleiche. Der Compiler wird diese auf die gleiche Weise optimieren.

Selbst wenn sie nicht gleich wären, wäre der Unterschied zum tatsächlichen Körper Ihrer Schleife vernachlässigbar. Sie sollten sich keine Gedanken über solche Mikrooptimierungen machen. Und Sie sollten keine Mikrooptimierungen vornehmen, es sei denn, Sie erstellen Leistungsprofile, um festzustellen, ob dies tatsächlich einen Unterschied macht.

3

Es ist das gleiche in Bezug auf die Geschwindigkeit. Der Compiler wird optimiert, wenn Sie i nicht später verwenden.

In Bezug auf Stil - Ich würde die Definition in das Schleifenkonstrukt setzen, wie es das Risiko reduziert, dass Sie in Konflikt geraten, wenn Sie später ein anderes i definieren.

9

Der Unterschied ist der Umfang.

for(int i = 1; i <= 100; ++i) 

ist in der Regel vorzuziehen, da dann der Umfang der i auf die for-Schleife eingeschränkt ist. Wenn Sie es vor der for-Schleife deklarieren, bleibt es bestehen, nachdem die for-Schleife beendet wurde und mit anderen Variablen kollidieren konnte. Wenn Sie es nur in der for-Schleife verwenden, gibt es keinen Grund, es länger als das zu lassen.

+0

In einigen der älteren Compiler ist der Umfang von i bis zum Ende der Funktion. das Verschieben des Int, aus der Schleife hält Sie gut mit anderen Compilern. – EvilTeach

+0

@EvilTech Nur ältere, nicht kompatible Compiler haben dieses Problem. Also, wenn Sie nicht denken, dass es eine gute Chance gibt, dass Ihr Code mit einem solchen Compiler verwendet wird, würde ich mir darüber keine Sorgen machen. Wenn es ein Problem ist, wird das Problem behoben, indem ein zusätzliches Paar Klammern um die for-Schleife gelegt wird. –

1

Mach dir keine Sorgen über Mikro-Optimierungen, lass den Compiler es machen. Wählen Sie, was am besten lesbar ist. Beachten Sie, dass die Deklaration einer Variablen innerhalb einer Initialisierungsanweisung for die Variable auf die for-Anweisung (C++ 03 § 6.5.3 1) beschränkt, obwohl das genaue Verhalten der Compiler variieren kann (einige können Sie auswählen). Wenn Code außerhalb der Schleife die Variable verwendet, deklarieren Sie sie außerhalb der Schleife. Wenn die Variable wirklich lokal für die Schleife ist, deklarieren Sie sie im Initialisierer.

-1

Es ist alles gleich.

1

Es wurde bereits erwähnt, dass der Hauptunterschied zwischen beiden der Anwendungsbereich ist.Stellen Sie sicher, dass Sie verstehen, wie Ihr Compiler den Umfang eines int behandelt deklariert als

for (int i = 1; ...;...) 

Ich weiß, dass, wenn MSVC++ verwenden 6, i ist noch im Rahmen außerhalb der Schleife, als ob es vor der Schleife deklariert wurden . Dieses Verhalten unterscheidet sich von VS2005, und ich müsste überprüfen, aber ich denke, die letzte Version von gcc, die ich verwendet habe. In beiden Compilern war diese Variable nur innerhalb der Schleife enthalten.

+0

Das ist ein bekannter Fehler in VC++ 6. Wenn Sie wirklich interessiert sind, umgeben Sie die for-Schleife mit einer anderen Reihe von Klammern. – jmucchiello

5

Nehmen wir an, das ursprüngliche Poster hatte eine Schleife, die wirklich optimiert werden sollte - jeder Befehl wurde gezählt. Wie können wir empirisch die Antwort auf seine Frage herausfinden?

GCC hat mindestens einen nützlichen, wenn nicht üblich verwendeten Schalter, '-S'. Es speichert die Assembly-Code-Version der .c-Datei und kann verwendet werden, um Fragen wie die OP-Posen zu beantworten. Ich schrieb ein einfaches Programm:

int main() 
{ 
    int sum = 0; 

    for(int i=1;i<=10;++i) 
    { 
     sum = sum + i; 
    } 
    return sum; 
} 

Und lief: gcc -O0 -std=c99 -S main.c, die Assemblierung-Version des Hauptprogramms zu schaffen. Hier ist der Inhalt von main.s (mit einigen der Flaum entfernt):

movl $0, -8(%rbp) 
    movl $1, -4(%rbp) 
    jmp  .L2 
.L3: 
    movl -4(%rbp), %eax 
    addl %eax, -8(%rbp) 
    addl $1, -4(%rbp) 
.L2: 
    cmpl $10, -4(%rbp) 
    jle  .L3 

Sie brauchen nicht ein Montage Experte zu sein, um herauszufinden, was los ist. Movl verschiebt Werte, addl fügt Dinge hinzu, cmpl vergleicht und jle steht für 'springen wenn kleiner als', $ ist für Konstanten. Es lädt 0 in etwas - das muss "Summe" sein, 1 in etwas anderes - ah, "ich"! Ein Sprung zu L2, wo wir den Vergleich mit 10 machen, springe zu L3, um das Add zu machen. Gehe nochmal zu L2 um den Vergleich zu wiederholen. Ordentlich! Eine for-Schleife.

Ändern Sie das Programm:

int main() 
{ 
    int sum = 0; 
    int i=1; 
    for(;i<=10;++i) 
    { 
     sum = sum + i; 
    } 
    return sum; 
} 

Rerun gcc und die resultierende Anordnung wird sehr ähnlich sein. Es gibt einige Dinge, die mit der Aufzeichnung von Zeilennummern passieren, also werden sie nicht identisch sein, aber die Assembly ist die gleiche. Gleiches Ergebnis mit dem letzten Fall. Also, auch ohne Optimierung ist der Code ungefähr gleich.

Aus Spaß, führen Sie gcc mit '-O3' anstelle von '-O' erneut aus, um die Optimierung zu aktivieren und die .s-Datei anzuzeigen.

main: 
movl $55, %eax 
ret 

gcc nicht nur herausgefunden wir ein for-Schleife wurden zu tun, aber auch klar, dass es war eine konstante Anzahl von Zeiten zu laufen hat die Schleife für uns bei der Kompilierung, rausgeschmissen ' ‚i‘ und ‚Summe‘ und hart die Antwort codiert - 55! Das ist SCHNELL - wenn auch ein bisschen künstlich.

Moral der Geschichte? Verbringen Sie Ihre Zeit damit, sicherzustellen, dass Ihr Code sauber und gut gestaltet ist. Code für Lesbarkeit und Wartbarkeit. Die Jungs, die von Mountain Dew und Cheetos leben, sind viel schlauer als wir und haben die meisten dieser einfachen Optimierungsprobleme für uns erledigt. Habe Spaß!

1
for(int i = 1; i <= 100; ++i) 

Dies ist am einfachsten zu lesen, außer für ANSI C/C89, wo es ungültig ist.

Verwandte Themen