问题
The following syntax is valid:
while (int i = get_data())
{
}
But the following is not:
do
{
} while (int i = get_data());
We can see why via the draft standard N4140
section 6.4:
1 [...]
condition: expression attribute-specifier-seqoptdecl-specifier-seq declarator = initializer-clause attribute-specifier-seqoptdecl-specifier-seq declarator braced-init-list2 The rules for conditions apply both to selection-statements and to the
for
andwhile
statements (6.5). [...]
and section 6.5
1 Iteration statements specify looping.
iteration-statement:while
( condition ) statementdo
statementwhile
( expression ) ;
Instead, you're forced to do something ugly like:
int i = get_data();
do
{
} while ((i = get_data())); // double parentheses sic
What is the rationale for this?
回答1:
It seems like scoping would be the issue, what would be the scope of i
declared in the while
portion of a do while
statement? It would seem rather unnatural to have a variable available within the loop when the declaration is actually below the loop itself. You don't have this issue with the other loops since the declarations comes before the body of the loop.
If we look at the draft C++ standard section [stmt.while]p2 we see that for the while statement that:
while (T t = x) statement
is equivalent to:
label:
{ // start of condition scope
T t = x;
if (t) {
statement
goto label;
}
} // end of condition scope
and:
The variable created in a condition is destroyed and created with each iteration of the loop.
How would we formulate this for the do while
case?
and as cdhowie points out if we look at section [stmt.do]p2 it says (emphasis mine):
In the do statement the substatement is executed repeatedly until the value of the expression becomes false. The test takes place after each execution of the statement.
which means the body of the loop is evaluated before we would even reach the declaration.
While we could create an exception for this case it would violate our intuitive sense that in general the point of declaration for a name is after we see the complete declaration(with some exceptions for example class member variables) with unclear benefits. Point of declaration is covered in section 3.3.2
.
回答2:
There are several reasons for why it would be difficult to allow.
The language sticks to the general rule that everything should be declared above the point of usage. In this case the variable declared in do-while
would be declared below its expected natural scope (the cycle body). Making this variable accessible inside the cycle would've required a special treatment for do-while
cycles. Even though we know examples of such special treatment (e.g. in-class member function bodies can see all class members, including the ones declared below), there's probably not much practical sense in doing it for do-while
cycles.
In case of do-while
these special treatment rules would also require finding a meaningful way of handling initialization of variables declared in this fashion. Note that in C++ language the lifetime of such variable is limited to one iteration of the loop, i.e. the variable is created and destroyed on each iteration. That means that for do-while
cycle the variable will always remain uninitialized, unless you introduce some rule that would somehow move the initialization to the beginning of the loop body. That would be quite confusing in my opinion.
回答3:
It would be very unnatural to have a declaration of i
after the block and to then be able to access it in the block. Declaration in for
and while
are nice short-hands that give limited-scope use to a variable that is needed in the loop logic.
Cleaner to do it this way:
int i;
do {
i = get_data();
// whatever you want to do with i;
} while (i != 0);
回答4:
This is because everything else follows the practice of declaring variables before you use them, eg:
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
}
This is because things are parsed top down, and because following this convention keeps things intuitive, thus why you can declare a while(int var < 10) because the scope of that var will be the area inside the loop, after the declaration.
The do while doesn't make any sense to declare a variable because the scope would end at the same time it would be checked because that's when that block is finished.
回答5:
Add this
#define do(cond) switch (cond) do default:
at the beginning of your code.
Now, you can write
do (int i = get_data())
{
// your code
} while ((i = get_data()));
It is important that this #define
does not break the original syntax of the do
keyword in do-while loop.
However, I admit that it is obscure.
回答6:
Your first syntax is valid while the second is not. However, your while loop will loop forever, even if your function get_data() returns 0. Not sure if that's exactly what you want to happen.
来源:https://stackoverflow.com/questions/27430640/why-cant-you-declare-a-variable-inside-the-expression-portion-of-a-do-while-loo