2014-12-11 2 views
32

Die folgende Syntax gilt:Warum können Sie keine Variable im Ausdrucksteil einer do while-Schleife deklarieren?

while (int i = get_data()) 
{ 
} 

Aber das Folgende nicht:

do 
{ 
} while (int i = get_data()); 

Wir warum über den Norm-Entwurf sehen:

[N4140/6.4]

1 [ ...]

condition: 
    expression 
    attribute-specifier-seqoptdecl-specifier-seq declarator = initializer-clause 
    attribute-specifier-seqoptdecl-specifier-seq declarator braced-init-list

2 Die Regeln für die Bedingungen gelten sowohl für Auswahl-Aussagen und die for und while Aussagen (6.5). [...]

[N4140/6.5]

1 Iterationsanweisungen angeben Looping.

int i = get_data(); 
do 
{ 
} while ((i = get_data())); // double parentheses sic 

Was ist der Grund dafür:

  iteration-statement: 
      while (condition) statement 
      dostatementwhile (expression) ;

Stattdessen sind Sie etwas hässlich wie zu tun gezwungen?

+5

Grund kann nicht sein, weil 'while' Bedingung außerhalb des' do-while' Bereichs liegt. Nun, warum können Sie nicht, am wahrscheinlichsten aufgrund von Grammatikeinschränkungen. – 101010

+0

Hinweis, wir finden hier Links zu den [Normentwürfen] (http://stackoverflow.com/q/81656). –

+0

Beachten Sie, dass Sie immer weitere Klammern umschließen können: '{int i; tue {...} während (...); } '. –

Antwort

38

Es scheint wie Scoping wäre das Problem, was wäre der Umfang der i im while Teil einer do while Erklärung erklärt? Es wäre eher unnatürlich, eine Variable innerhalb der Schleife verfügbar zu haben, wenn die Deklaration tatsächlich unterhalb der Schleife selbst liegt. Dieses Problem tritt bei den anderen Schleifen nicht auf, da die Deklarationen vor dem Schleifenkörper stehen.

Wenn wir die draft C++ standard betrachten, sehen wir aus dem Abschnitt 6.5.1Die while-Anweisung, dass für die während Aussage dass:

while (T t = x) statement 

entspricht:

label: 
{ // start of condition scope 
    T t = x; 
    if (t) { 
     statement 
    goto label; 
    } 
} // end of condition scope 

und:

Die in einer Bedingung erstellte Variable wird bei jeder Iteration der Schleife zerstört und erstellt.

Wie würden wir das für den do while Fall formulieren?

und als cdhowie weist darauf hin, wenn wir in Abschnitt sehen 6.5.2Die Aussage machen es sagt (Hervorhebung von mir):

In der do-Anweisung die Subanweisung so oft, bis der Wert der ausgeführt wird, Ausdruck wird falsch. Der Test findet nach jeder Ausführung der Anweisung statt.

was bedeutet, dass der Körper der Schleife ausgewertet wird, bevor wir sogar die Deklaration erreichen würden. Wenn wir eine Ausnahme für diesen Fall erstellen könnten, würde dies unseren intuitiven Sinn verletzen, dass im Allgemeinen der Punkt der Deklaration für einen Namen ist, nachdem wir die vollständige Deklaration (mit einigen Ausnahmen zum Beispiel Klassenelementvariablen) mit unklarem Punkt sehen Leistungen. Punkt der Erklärung ist in Abschnitt 3.3.2 abgedeckt.

+0

Ich habe gerade darüber nachgedacht zu geben diese Antwort (einschließlich eines Samples), aber das wäre dasselbe wie Shadowing 'i' innerhalb eines' for() 'loops body. Das Verhältnis muss etwas anderes sein. –

+2

@ πάνταῥεῖ Ich denke, die Antwort ist mehr darüber, wie es wirklich keinen Sinn machen würde, wenn die Variablendeklaration * nach * dem Schleifenkörper, in dem sie gültig ist, kommt, und nicht über irgendein Abschattungspotential. – cdhowie

+14

(Zumal der Rumpf einer do ... while-Schleife einmal ausgeführt wird, bevor die Bedingung überhaupt ausgewertet wird, macht es also keinen Sinn, eine Deklaration, insbesondere eine mit Zuweisung, in den Schleifenzustand zu bringen.) – cdhowie

8

Es wäre sehr unnatürlich, nach dem Block eine Deklaration von i zu haben und dann im Block darauf zugreifen zu können. Die Deklaration in for und while sind nette Kurzhände, die einer Variable, die in der Schleifenlogik benötigt wird, begrenzten Nutzen geben.

Reiniger es auf diese Weise zu tun:

int i; 
do { 
    i = get_data(); 
    // whatever you want to do with i; 
} while (i != 0); 
20

Es gibt mehrere Gründe dafür, warum es schwierig wäre, zu ermöglichen.

Die Sprache bleibt an der allgemeinen Regel, dass alles über den Punkt der Verwendung deklariert werden sollte. In diesem Fall würde die Variable, die in do-while deklariert ist, unter ihren erwarteten natürlichen Umfang (der Körper des Körpers) erklärt werden. Um diese Variable innerhalb des Zyklus zugänglich zu machen, wäre eine spezielle Behandlung für do-while Zyklen erforderlich gewesen. Auch wenn wir Beispiele für eine solche spezielle Behandlung kennen (z. B. klasseninterne Mitgliederfunktionskörper können alle Klassenmitglieder sehen, einschließlich derjenigen, die unter unter deklariert sind), gibt es wahrscheinlich keinen praktischen Sinn dafür, dies für do-while Zyklen zu tun.

Im Fall von do-while erfordern diese speziellen Behandlungsregeln auch die Suche nach einem sinnvollen Verfahren zur Behandlung der Initialisierung von Variablen, die auf diese Weise deklariert wurden. Man beachte, dass in C++ - Sprache die Lebensdauer einer solchen Variablen auf eine Iteration der Schleife beschränkt ist, d. H. Die Variable wird bei jeder Iteration erzeugt und zerstört. Das bedeutet, dass die Variable für do-while Zyklus immer nicht initialisiert bleibt, es sei denn, Sie führen eine Regel ein, die die Initialisierung in den Anfang des Schleifenkörpers verschieben würde. Das wäre meiner Meinung nach ziemlich verwirrend. Diese

5

ist, weil alles andere folgt die Praxis Variablen deklarieren, bevor Sie sie verwenden, zB:

public static void main(String[] args){ 
    // scope of args 
} 

for(int i=1; i<10; i++){ 
    // scope of i 
} 


{ 
... 
int somevar; 
//begin scope of var 

... 

//end of scope of var 
} 

Dies liegt daran, die Dinge analysiert oben nach unten, und weil diese Konvention folgende hält die Dinge intuitiv, also warum Sie kann eine while deklarieren (int var < 10), da der Gültigkeitsbereich dieser Variablen der Bereich innerhalb der Schleife nach der Deklaration ist.

Das Ausführen von do while macht keinen Sinn, eine Variable zu deklarieren, da der Bereich zur selben Zeit enden würde, wenn er überprüft würde, weil dann der Block fertig ist.

-2

Ihre erste Syntax ist gültig, die zweite nicht. Ihre while-Schleife wird jedoch für immer endlos fortgesetzt, auch wenn Ihre Funktion get_data() 0 zurückgibt. Nicht sicher, ob das genau das ist, was Sie wollen.

+1

Die Frage direkt besagt, dass ein Beispiel gültig ist und das andere nicht; Die Frage lautet: Warum wird die Sprache auf diese Weise angegeben? (Im Gegensatz zu den meisten SO-Fragen ist dies keine "debug my code for me" -Frage.) –

0

diesen

#define do(cond) switch (cond) do default: 

am Anfang des Codes hinzufügen.

Jetzt können Sie

do (int i = get_data()) 
{ 

    // your code 

} while ((i = get_data())); 

schreiben Es ist wichtig, dass diese #define nicht die ursprüngliche Syntax des do Schlüsselwort in do-while-Schleife nicht bricht.

Allerdings gebe ich zu, dass es obskur ist.

Verwandte Themen