Variable in Schleife anlegen schlecht?



  • Hallo,

    ist es schlecht, wenn ich eine Variable in der schleife anlege?

    for(int i=0; i<10; i++) {
    float foo = ...
    ...
    }
    

    Wird dann bei jedem Durchlauf eine neue Variable auf dem Stack gelegt (und die alte gelöscht)?



  • erstens, ja wird natürlich immer wieder angelegt
    zweitens: wozu brauchst du das? Wenn du ein problem hast wo du denkst du brauchst es können wir dir sicher besser helfen



  • Ich würde mal sagen, der Compiler muss sicherstellen, dass sich die Variable so verhält als würde sie jedes mal neu erstellt.

    Da der Wert eines Floats aber vor seiner initialisierung undefiniert ist kann es IMO gut sein, dass der alte Wert da weiterhin drinnesteht und nichts neu angelegt wurde.

    Btw: Scott Meyers empfielht in »Effective C++« variablen so spät als möglich anzulegen und explizit auch, Variablen erst im Rumpf einer Schleife anzulegen, wenn diese nur dort benötigt werden 😉 => ich würde mal davon ausgehen dass du keinen Leistungsunterschied merkst.

    EDIT://

    int main()
    {
            /*float f;*/
    	for (unsigned a(0); a < 10; a++)
    	{
    		/*float */f = 12;
    	}
    }
    

    Außen:

    .file	"loop.cpp"
    	.text
    	.align 2
    .globl main
    	.type	main, @function
    main:
    .LFB2:
    	leal	4(%esp), %ecx
    .LCFI0:
    	andl	$-16, %esp
    	pushl	-4(%ecx)
    .LCFI1:
    	pushl	%ebp
    .LCFI2:
    	movl	%esp, %ebp
    .LCFI3:
    	pushl	%ecx
    .LCFI4:
    	subl	$16, %esp
    .LCFI5:
    	movl	$0, -8(%ebp)
    	jmp	.L2
    .L3:
    	movl	$0x41400000, %eax
    	movl	%eax, -12(%ebp)
    	addl	$1, -8(%ebp)
    .L2:
    	cmpl	$9, -8(%ebp)
    	jbe	.L3
    	movl	$0, %eax
    	addl	$16, %esp
    	popl	%ecx
    	popl	%ebp
    	leal	-4(%ecx), %esp
    	ret
    .LFE2:
    	.size	main, .-main
    .globl __gxx_personality_v0
    	.ident	"GCC: (GNU) 4.2.3 20080114 (prerelease) (Debian 4.2.2-7)"
    	.section	.note.GNU-stack,"",@progbits
    

    Innen

    .file	"loop.cpp"
    	.text
    	.align 2
    .globl main
    	.type	main, @function
    main:
    .LFB2:
    	leal	4(%esp), %ecx
    .LCFI0:
    	andl	$-16, %esp
    	pushl	-4(%ecx)
    .LCFI1:
    	pushl	%ebp
    .LCFI2:
    	movl	%esp, %ebp
    .LCFI3:
    	pushl	%ecx
    .LCFI4:
    	subl	$16, %esp
    .LCFI5:
    	movl	$0, -12(%ebp)
    	jmp	.L2
    .L3:
    	movl	$0x41400000, %eax
    	movl	%eax, -8(%ebp)
    	addl	$1, -12(%ebp)
    .L2:
    	cmpl	$9, -12(%ebp)
    	jbe	.L3
    	movl	$0, %eax
    	addl	$16, %esp
    	popl	%ecx
    	popl	%ebp
    	leal	-4(%ecx), %esp
    	ret
    .LFE2:
    	.size	main, .-main
    .globl __gxx_personality_v0
    	.ident	"GCC: (GNU) 4.2.3 20080114 (prerelease) (Debian 4.2.2-7)"
    	.section	.note.GNU-stack,"",@progbits
    

    Unterschied

    --- aussen.S	2008-02-08 20:14:07.000000000 +0100
    +++ innen.S	2008-02-08 20:14:23.000000000 +0100
    @@ -18,14 +18,14 @@
     .LCFI4:
     	subl	$16, %esp
     .LCFI5:
    -	movl	$0, -8(%ebp)
    +	movl	$0, -12(%ebp)
     	jmp	.L2
     .L3:
     	movl	$0x41400000, %eax
    -	movl	%eax, -12(%ebp)
    -	addl	$1, -8(%ebp)
    +	movl	%eax, -8(%ebp)
    +	addl	$1, -12(%ebp)
     .L2:
    -	cmpl	$9, -8(%ebp)
    +	cmpl	$9, -12(%ebp)
     	jbe	.L3
     	movl	$0, %eax
     	addl	$16, %esp
    

    GNU GCC 4.2.3-pre (Debian Lenny)

    EDIT://
    Ganz ohne Optimierung und für mich sieht das nach keinerlei Performance-Unterschieden aus



  • @XaTrIxX: So natürlich ist das überhaupt nicht, dass die jedes Mal neu angelegt wird.

    @darthdespotism: Das hätte ich nicht gedacht, dass es sogar empfohlen wird Variablen im Schleifenrumpf anzulegen.
    Wenn ich jetzt noch Assembler könnte, hätte ich bestimmt einen noch tieferen Durchblick. 😃



  • Das Diff sagt aus: Die Codes brauchen exakt die gleiche Anzahl CPU-Takte 😉


  • Mod

    darthdespotism schrieb:

    Ganz ohne Optimierung und für mich sieht das nach keinerlei Performance-Unterschieden aus

    Und was hat das mit der Frage zu tun?



  • camper schrieb:

    darthdespotism schrieb:

    Ganz ohne Optimierung und für mich sieht das nach keinerlei Performance-Unterschieden aus

    Und was hat das mit der Frage zu tun?

    Der OP hiess "Performancefrage"


  • Mod

    LordJaxom schrieb:

    camper schrieb:

    darthdespotism schrieb:

    Ganz ohne Optimierung und für mich sieht das nach keinerlei Performance-Unterschieden aus

    Und was hat das mit der Frage zu tun?

    Der OP hiess "Performancefrage"

    Eben. Was hat "nicht optimiert" eines inhaltslosen Programmes mit "Performance" im Allgemeinen zu tun?



  • Die eingebauten Typen machen keinen Geschwindigkeitsunterschied.

    Nur wenn nicht-eingebaute Typen brauchst, macht es einen Unterschied.



  • camper schrieb:

    Eben. Was hat "nicht optimiert" eines inhaltslosen Programmes mit "Performance" im Allgemeinen zu tun?

    Es zeigt in diesem Fall, dass die Variable nicht "immer wieder auf dem Stack gelegt und dann wieder gelöscht" wird - wie es im OP gefragt wird. Das wird in inhaltsvollen Programmen und mit anderen integralen Typen nicht anders sein.

    drakon schrieb:

    Nur wenn nicht-eingebaute Typen brauchst, macht es einen Unterschied.

    Klar, weil das Objekt jedesmal neu konstruiert wird, selbst wenn es nicht neu allokiert wird (auf dem Stack, s.o.). Da sollte man dann abwägen ob es besser ist das Objekt ausserhalb der Schleife zu definieren und innerhalb wiederzuverwenden. Aber selbst hier kann man IMHO nicht pauschal sagen, dass eine Wiederverwendung (etwa durch ein clear()) besser wäre als eine Neukonstruktion.



  • LordJaxom schrieb:

    Aber selbst hier kann man IMHO nicht pauschal sagen, dass eine Wiederverwendung (etwa durch ein clear()) besser wäre als eine Neukonstruktion.

    Ja, das könnte sein. Weiss nicht genau. Das müsste man fast einmal testen. Denke kommt auch noch die Optimierung des Compilers an, aber ein eigenes Objekt wird man so in einer Schlaufe ja selten brauchen... Auf jedenfall habe ich das noch nie entdeckt..


Anmelden zum Antworten