TL; DR
ケース内で初期化子または重要なオブジェクトを使用して変数を宣言できる唯一の方法は、ループまたはifステートメントのような独自のスコープを持つブロックスコープを使用する{}
か、他の制御構造を導入することです。
ゴリー詳細
我々はそれを見ることができるケースがちょうどされている文ラベルのようなラベルで使用するのgoto文を(これはで覆われているC ++のドラフト標準のセクション6.1ラベル付きステートメント)、我々はセクションから見ることができます6.7
段落3ジャンプが宣言を渡すことを、多くの場合、許可されていません、初期化付きのものを含む:
ブロックに転送することは可能ですが、初期化で宣言をバイパスする方法ではできません。自動ストレージ期間を持つ変数がスコープ内にないポイントからスコープ内にあるポイントに87をジャンプするプログラムは、変数がスカラー型、自明なデフォルトコンストラクターおよび自明なデストラクタを持つクラス型でない限り、形式が正しくありません。これらのタイプのいずれかのcv修飾バージョン、または前述のタイプのいずれかの配列であり、初期化子なしで宣言されています(8.5)。
この例を提供します:
void f() {
// ...
goto lx; // ill-formed: jump into scope of a
ly:
X a = 1;
// ...
lx:
goto ly; // OK, jump implies destructor
// call for a followed by construction
// again immediately following label ly
}
ここにいくつかの微妙な点があることに注意してください。たとえば、初期化されていないスカラー宣言を飛び越すことができます。次に例を示します。
switch( n )
{
int x ;
//int x = 10 ;
case 0:
x = 0 ;
break;
case 1:
x = 1 ;
break;
default:
x = 100 ;
break ;
}
完全に有効です(実例)。もちろん、それぞれの場合に同じ変数を宣言したい場合は、それぞれに独自のスコープが必要ですが、switchステートメント以外でも同じように機能するため、大きな驚きではありません。
初期化のジャンプを許可しない理由については、欠陥レポート467が少し異なる問題をカバーしていますが、自動変数の妥当なケースを提供します。
[...]自動変数は、明示的に初期化されていない場合、トラップ表現を含む不確定な(「ガベージ」)値を持つ可能性があります[...]
スイッチ内のスコープを複数のケースに拡張する場合を見ると、おそらくもっと興味深いでしょう。この最も有名な例は、おそらく次のようなDuffのデバイスです。
void send( int *to, const int *from, int count)
{
int n = (count + 7) / 8;
switch(count % 8)
{
case 0: do { *to = *from++; // <- Scope start
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while(--n > 0); // <- Scope end
}
}