2015-12-28 5 views
12

den Standard als der N4567 verbietet einige Arten von Wieder Erklärung eines Namens in einem Zustand zuvor erklärt wie folgt-nach der Norm (§3.3.3/4):Was bedeutet der Standard durch "eine nachfolgende Bedingung dieser Aussage"?

Namen in der deklarierten for-init-Anweisung, die for-range-Deklaration und in der Bedingung von if-, while-, for- und switch-Anweisungen sind lokal für die if-, while-, for- oder switch-Anweisung (einschließlich der kontrollierten Anweisung) und dürfen nicht in einer nachfolgenden Bedingung dieser Anweisung noch im äußersten Block (oder, für die if-Anweisung, irgendeiner der äußersten Blöcke) der kontrollierten Aussage redeclariert werden; siehe 6.4.

jedoch in Anbetracht der Tatsache, dass der folgende Code kompiliert fein,

int main(void) { 
    if (int i=10) 
     if (int i=20) 
      ; 
    return 0; 
} 

es scheint mir unklar, was genau „eine nachfolgende Bedingung dieser Aussage“ steht.

+6

Vielleicht bezieht es sich auf die Situation für 'for':' für (int i = 0; int i = 1;); '. Es gibt eine nachfolgende Bedingung nach der ursprünglichen Erklärung von "i". Die Formulierung für "wenn", "irgendeinen der äußersten Blöcke", zeigt an, dass es die else-Zweige eines "if" als Teil dieses "if" betrachtet, also denke ich, dass es sich auch auf "if (int i = 1); sonst wenn (int i = 1); –

+1

Ich denke, es geht darum, einen Namen zweimal unter denselben Bedingungen zu deklarieren. Das sind zwei verschiedene 'if'-Aussagen mit unterschiedlichen Bedingungen. – Cornstalks

+0

Ah, die Struktur ist 'if (...) stmt; sonst stmt', also glaube ich nicht, dass mein Beispiel mit den beiden Wenns übereinstimmt. "Jeder der äußersten Blöcke" soll sich eindeutig auf "if (int i = 1) {int i = 2; } else {int i = 3; } 'und nicht zu 'if (int i = 1); sonst wenn (...) {int i = 2; } '(IMO). –

Antwort

2

Die markierten „dass“ die Aussage bedeutet if, while, for und switch Anweisung, die den Namen definiert ist, und nicht auf die Unteranweisung durch den Zustand oder die Iteration gesteuert.

6,4/3::

Dies wird erklärt Ein Name durch eine Erklärung in einem Zustand eingeführt (entweder durch den DECL-Spezifizierer-seq oder die Deklarationen tor des Zustand eingeführt) ist in Umfang von seiner Deklaration bis Ende die von der Bedingung kontrollierten Unteranweisungen. Wenn der Name im äußersten Block einer durch die -Bedingung gesteuerten Unteranweisung erneut deklariert wird, ist die Deklaration, die den Namen erneut deklariert, fehlerhaft.

Aus diesem Grund ist der folgende statment gilt:

if (int i=10) 
    if (int i=20) 
     ; 

Der Compiler die Deklaration von if (int i=20) nicht als eine andere Bedingung der gleichen if-Anweisung, sondern als Regel Subanweisung analysiert. Und da die zweite Deklaration von i in der Bedingung stattfindet, wird sie im äußeren Block der kontrollierten Aussage nicht berücksichtigt.

dagegen die folgende fast gleichwertige Aussage ist nicht gültig, da es die äußere Block Einschränkung bricht:

if (int k=10) { 
    int k=20; // <===== ouch ! redefinition in the outerblock 
    if (k) 
     cout <<"oops"; 
} 

daher der einzige Fall, in dem Sie eine "auflösenden Bedingung der dass Aussage haben "ist die for Aussage. Die standandard Highlights dieser besonderen Situation, durch die Begründung der Beschränkung geben, die Sie mit einer klareren Formulierung zitiert habe:

6.5.3/1: (...) Namen in dem deklarierte für-init-Anweisung sind in der gleichen deklarative-Region wie die in der Bedingung erklärt,

dh die gleichen Namen in der init und in dem Zustand, erklärt die ODR würde brechen .

+0

Warum zählt das 'if (int i = 20)' nicht als Deklaration des Namens im äußersten Block der Subanweisung? –

+1

@ M.M weil, wenn Sie die Variable in der Bedingung deklarieren, ist es in der Bedingung und der kontrollierten Aussage sichtbar, aber nicht außerhalb. Aus diesem Grund können Sie die Variablen, die in for in ouside forstment deklariert sind, nicht (mehr) wiederverwenden wie 'für (int i = ...) {...} if (i == ...) handle_special_case() ; es sei denn, Sie verwenden einige nicht standardmäßige Erweiterungen, die in einigen Compilern vorhanden sind, um älteren Code zu unterstützen. – Christophe

+0

@ M.M [hier ein MSDN-Beispiel der Erweiterung] (https://msdn.microsoft.com/en-us/library/84wcsx8x.aspx), das sich auf den begrenzten Umfang der Variablen bezieht, die in der Initialisierung/Bedingung definiert ist – Christophe