Betrachten Sie den folgenden Code:
#include <iostream>
using namespace std;
int main()
{
int x, y, i;
cin >> x >> y >> i;
switch(i) {
case 1:
// int r = x + y; -- OK
int r = 1; // Failed to Compile
cout << r;
break;
case 2:
r = x - y;
cout << r;
break;
};
}
G ++ beschwert sich crosses initialization of 'int r'
. Meine Fragen sind:
- Was ist
crosses initialization
? - Warum besteht der erste Initialisierer
x + y
die Kompilierung, letzterer ist jedoch fehlgeschlagen? - Was sind die Probleme der sogenannten
crosses initialization
?
Ich weiß, dass ich Klammern verwenden sollte, um den Umfang von anzugeben r
, aber ich möchte wissen, warum, zum Beispiel, warum Nicht-POD nicht in einer Switch-Anweisung mit mehreren Fällen definiert werden konnte.
c++
initialization
Jichao
quelle
quelle
Antworten:
Die Version mit
int r = x + y;
wird auch nicht kompiliert.Das Problem ist, dass es möglich ist
r
, zum Gültigkeitsbereich zu gelangen, ohne dass der Initialisierer ausgeführt wird. Der Code würde gut kompiliert, wenn Sie den Initialisierer vollständig entfernen würden (dh die Zeile würde lesenint r;
).Das Beste, was Sie tun können, ist, den Umfang der Variablen zu begrenzen. Auf diese Weise werden Sie sowohl den Compiler als auch den Leser zufriedenstellen.
Der Standard sagt (6.7 / 3):
quelle
int r = x + y
.Sie sollten den Inhalt der
case
in Klammern setzen, um ihm den Gültigkeitsbereich zu geben. Auf diese Weise können Sie lokale Variablen darin deklarieren:quelle
Es ist möglich, in einen Block zu übertragen, jedoch nicht so, dass Deklarationen bei der Initialisierung umgangen werden. Ein Programm, das von einem Punkt, an dem sich eine lokale Variable mit automatischer Speicherdauer nicht im Gültigkeitsbereich befindet, zu einem Punkt springt, an dem sie sich im Gültigkeitsbereich befindet, ist fehlerhaft, es sei denn, die Variable hat den POD-Typ und wird ohne Initialisierer deklariert.
Die Übertragung von der Bedingung einer switch-Anweisung auf eine Fallbezeichnung wird in dieser Hinsicht als Sprung angesehen.
quelle
Ich schlage vor, Sie fördern Ihre
r
Variable vor derswitch
Anweisung. Wenn Sie eine Variable blockübergreifend verwenden möchtencase
(oder denselben Variablennamen, aber unterschiedliche Verwendungen), definieren Sie sie vor der switch-Anweisung:Einer der Vorteile besteht darin, dass der Compiler nicht in jedem Block eine lokale Zuordnung (auch bekannt als Push auf den Stapel) durchführen muss
case
.Ein Nachteil dieses Ansatzes besteht darin, dass Fälle in andere Fälle "fallen" (dh ohne Verwendung
break
), da die Variable einen vorherigen Wert hat.quelle