In diesem Beispiel, obwohl ich nie die Variablen WNDCLASSEX, x, y, cx, cy verwenden werde, werden sie immer noch Speicher verwenden, wenn ich in der Nachrichtenschleife bin:
%Vor%Aber ich wundere mich, wenn ich sie in einen Bereich setze, würden sie immer noch Speicher während der Nachrichtenschleife verwenden? z.B.
%Vor%oder vielleicht, wenn ich sie in zwei Funktionen und nannte sie in Winmain, z.
%Vor%würde das verhindern, dass sie den Speicher verwenden?
Der Compiler hat viel Spielraum für den Umgang mit einfachen Locals, wie Sie es in Ihren Beispielen haben. Sie können auf dem Stapel leben, sie können nur als unmittelbare Werte im Maschinencode existieren oder sie können nur in Registern leben. Stack-Speicherplatz wird normalerweise beim Eintritt in eine Funktion zugewiesen. Der Compiler subtrahiert einen Wert vom Stack-Pointer, um Platz für alle Locals zu schaffen. Bei Rückgabe der Funktion wird der Stapelzeiger wieder auf seinen ursprünglichen Wert zurückgesetzt. Dies wird normalerweise nicht beim Beenden verschiedener Bereichsblöcke durchgeführt. Die meisten Compiler werden versuchen, Stapelspeicherplatz aggressiv wiederzuverwenden, sobald keine Variablen mehr verwendet werden. In Ihrem Beispiel wäre es vollkommen legal, dass x und msg die exakt gleiche Adresse auf dem Stack haben, da ihre Verwendung nicht überlappt ist.
Meine Antwort auf Diese Frage befasst sich ausführlicher damit, wie lokale Variablen auf dem Stack zugewiesen werden.
In Ihren Beispielen haben die Konstanten cx und cy höchstwahrscheinlich keinen Speicher, der sie zur Laufzeit unterstützt, und sie sind nur unmittelbare Werte im generierten Code. x und y werden höchstwahrscheinlich in Registern leben, bis sie für den Aufruf von CreateWindow auf den Stapel geschoben werden müssen. wc und msg werden fast definitiv auf dem Stapel sein.
Sie sollten sich keine Gedanken über Mikrooptimierungen auf dieser Ebene machen. Lassen Sie den Compiler Platz für lokale Variablen reservieren, wie er es für richtig hält. Sie haben standardmäßig einen Stack von 1 MB, die von diesen Variablen verbrauchte Datenmenge würde nicht einmal als Rauschen registriert. Verbringen Sie Ihre Zeit damit, sich um interessantere Probleme zu kümmern.
Wahrscheinlich nicht, aber das ist ein Implementierungsdetail. Sie sind jedoch zerstört worden (Destruktor-Aufrufe wurden gemacht, wenn es welche gibt). Ob und wann das System den für die automatische Speicherung verwendeten Speicher wiederherstellt, ist vom Standard nicht festgelegt. Die meisten geben es ziemlich sofort afaik zurück.
Ein magischer Ratschlag: Vertraue deinem Compiler. Optimiert. Es ist schlau. Es optimiert besser als die meisten von uns könnten.
Wenn Sie unsicher sind, verwenden Sie einen Profiler oder untersuchen Sie die Assembler-Ausgabe des Compilers nach Optimierungen. Aber denken Sie daran - triviale Optimierungen sollten Sie in Ihrem Code nicht tun, da dies sinnlos ist und nur die Lesbarkeit Ihres Codes beeinträchtigt.
Einige Variablen (insbesondere die Konstanten) verwenden keinen beliebigen Speicher im Stack, da sie entweder auf CPU-Register abgebildet oder direkt in eine Assembler-Anweisung eingebettet werden.
Dies bedeutet, dass die Codes:
%Vor%und
%Vor%würde genau zu der gleichen Sache kompilieren (wenn die Variablen nie wieder verwendet werden).
Mach dir ernsthaft keine Sorgen. Wenn Sie optimieren möchten, optimieren Sie vom algorithmischen Standpunkt aus gesehen nicht die Syntax.
Nun, ich bin mir nicht sicher, ob sie Speicher benutzen oder was der Standard dazu sagt.
Was ich weiß ist, dass am Ende eines Speicherblocks {} der Destruktor aufgerufen wird und Variablen nicht erreichbar sind. Dies könnte bedeuten, dass es zumindest nicht wiederverwendet werden kann, aber zumindest wiederverwendet werden kann.
Beispiel:
%Vor%Bearbeiten: Danke Tomalak Geret'kal;)
Ihre deklarierten Variablen innerhalb der {} 'gehen aus dem Gültigkeitsbereich und gehen verloren. In der Tat erhalten Sie einen Kompilierungsfehler, wenn Sie versuchen, sie außerhalb des Blocks zu verwenden: 'x' ist nicht deklariert. Dies ist jedoch schlampig. Machen Sie einfach eine Funktion für diesen Code, wie Sie in Ihrer Bearbeitung gesagt haben. Halten Sie Ihre Haupt () so wenige Zeilen wie möglich ist einfach Programmierpraxis.
Sie werden nicht. Sie werden nur bis zum Ende ihres umschließenden Blocks leben.
Wenn Sie sie in einen verschachtelten Bereich innerhalb der Funktion einfügen (Ihre erste Option), wird die Variable nicht mehr zugreifbar, wenn die Steuerung das Ende des Bereichs erreicht (entweder ein Kompilierungsfehler, wenn Sie sie direkt verwenden, oder nicht definiertes Laufzeitverhalten) Sie speichern einen Zeiger auf einen von ihnen), ihre Destruktoren werden ausgeführt (wenn es Destruktoren gibt), und die Implementierung kann ihren Speicherplatz innerhalb des Stapelrahmens wiederverwenden. Aber die Standards erfordern nicht, dass sie den Platz wiederverwenden.
Wenn Sie Ihre Funktion in zwei teilen (Ihre zweite Option) ... in Bezug auf Standard-Haarspalterei gibt es keinen Unterschied! Wenn die Funktion zurückkehrt, werden die Variablen unzugänglich, ihre Destruktoren werden ausgeführt, und die Implementierung kann ihren Speicherplatz wiederverwenden, aber es ist nicht erforderlich. Und dort haben ernsthafte Implementierungen gewesen - wenn auch nicht von C / C ++ - die diese Erinnerung nicht sofort wiederverwenden: sehen Sie am berühmtesten die Zeitung " Cheney über die MTA "
Aber alle Implementierungen von C / C ++ , von denen ich derzeit weiß, dass den Speicher für die lokalen Variablen einer Funktion wieder herstellt, wenn eine Funktion zurückkehrt. Die Wiederverwendung von Speicher für verschachtelte lokale Variablen ist weniger sicher. Auf jeden Fall, wie einige andere Leute erwähnt haben, lohnt es sich in diesem Zusammenhang nicht, sich um ein paar Dutzend Bytes Stapelspeicher zu kümmern.
Persönlich würde ich Ihren Code in zwei Funktionen aufteilen, nur weil auf diese Weise jede Funktion nur eine Aufgabe ausführt. Das ist in der Regel besser für die langfristige Wartung.
Im Allgemeinen ja, wenn sich die Variable überhaupt auf dem Stack befindet, wird für die gesamte Dauer der umschließenden Funktion Platz auf dem Stack belegt. Compiler berechnen normalerweise die maximale Menge an Speicherplatz, die die Variablen der Funktion belegen könnten, und dann veranlassen sie die Funktion, all diese Funktionen auf einmal zuzuweisen, wenn die Funktion zum ersten Mal eingegeben wird. Konstruktoren und Destruktoren werden jedoch immer noch beim Ein- und Ausstieg der inneren Bereiche aufgerufen. Platz für Variablen in einem Bereich kann wiederverwendet werden, um Variablen aus einem separaten Bereich darzustellen.