次の構文が有効です。
while (int i = get_data())
{
}
しかし、以下はそうではありません:
do
{
} while (int i = get_data());
ドラフト標準を介して理由を確認できますN4140
セクション6.4:
1 [...]
条件: 式属性指定子-seqoptdecl-specifier-seq declarator = initializer-clauseattribute-specifier-seqoptdecl-specifier-seq宣言子braced-init-list2条件の規則は、selection-statementsと
for
およびwhile
ステートメントの両方に適用されます(6.5)。 [...]
およびセクション6.5
1反復ステートメントはループを指定します。
iteration-statement:while
(condition)statementdo
ステートメントwhile
(式);
代わりに、次のような醜いことをする必要があります。
int i = get_data();
do
{
} while ((i = get_data())); // double parentheses sic
これの理論的根拠は何ですか?
スコープが問題になるようですが、do while
ステートメントのi
部分で宣言されたwhile
のスコープは何でしょうか?宣言が実際にループ自体の下にあるときに、ループ内で変数を使用できるようにするのはかなり不自然に思えます。宣言はループの本体の前にあるため、他のループではこの問題は発生しません。
ドラフトC++標準 セクション [stmt.while] p2 を見ると、whileステートメントであることがわかります。
while (T t = x) statement
と同等です:
label:
{ // start of condition scope
T t = x;
if (t) {
statement
goto label;
}
} // end of condition scope
そして:
条件で作成された変数は破棄され、ループが繰り返されるたびに作成されます。
do while
の場合、これをどのように定式化しますか?
そして、cdhowieがセクションを見ると指摘しているように、 [stmt.do] p2 それは(emphasis mine)と言っています:
Doステートメントでは、式の値がfalseになるまで、サブステートメントが繰り返し実行されます。 テストはステートメントの各実行後に行われます。
つまり、宣言に到達する前に、ループの本体が評価されます。
この場合の例外を作成することはできますが、一般に名前の宣言のポイントは、完全な宣言(クラスメンバー変数などのいくつかの例外を除く)を確認した後であるという直感に違反します。不明確な利点。 宣言のポイントはセクション3.3.2
でカバーされています。
許可するのが難しい理由はいくつかあります。
言語は、すべてを宣言する必要があるという一般的な規則に固執します上記使用ポイント。この場合、do-while
で宣言された変数は、以下予想される自然なスコープ(サイクル本体)として宣言されます。サイクル内でこの変数にアクセスできるようにするには、do-while
サイクルに特別な処理が必要でした。そのような特別な扱いの例を知っていても(たとえば、クラス内のメンバー関数本体は、宣言されたものを含むすべてのクラスメンバーを見ることができます以下)、do-while
サイクルでそれを行うことにはおそらくあまり実用的な意味がありません。
do-while
の場合、これらの特別な処理ルールでは、この方法で宣言された変数の初期化を処理する意味のある方法を見つける必要もあります。 C++言語では、このような変数の有効期間はループの1回の反復に制限されていることに注意してください。つまり、変数は反復ごとに作成および破棄されます。つまり、do-while
サイクルでは、ループ本体のbeginningに初期化を移動するルールを導入しない限り、変数は常に初期化されないままになります。それは私の意見ではかなり混乱するでしょう。
ブロックの後にi
の宣言をして、ブロック内でそれにアクセスできるようにするのは非常に不自然です。 for
とwhile
の宣言は、ループロジックで必要な変数に限定されたスコープの使用を与える優れた省略形です。
このようにするためのクリーナー:
int i;
do {
i = get_data();
// whatever you want to do with i;
} while (i != 0);
これは、他のすべてが、変数を使用する前に変数を宣言する慣行に従っているためです。例:
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
}
これは、物事がトップダウンで解析されるためであり、この規則に従うと物事が直感的に保たれるため、while(int var <10)を宣言できるのは、そのvarのスコープが宣言後のループ内の領域になるためです。
Do whileは、変数を宣言する意味がありません。スコープが終了すると同時に、そのブロックが終了するためにチェックされるためです。
これを追加
#define do(cond) switch (cond) do default:
コードの最初に。
今、あなたは書くことができます
do (int i = get_data())
{
// your code
} while ((i = get_data()));
これが重要です#define
は、do-whileループでdo
キーワードの元の構文を壊しません。
しかし、私はそれがあいまいであることを認めます。