On Oct 27, 11:08 am, terminator <farid.mehr...@gmail.comwrote:
On Oct 26, 11:16 am, James Kanze <james.ka...@gmail.comwrote:
Sorry to terminate again ;I can not see what the scope of for
initializer is. I used to take the following two as equivalent
code:
_1st:
for(int init =0 ;condition ;inrement)
statement;
_2nd:
start_loop:{
int init=0;
for(;condition;increment)
{statement;};
};//destroy init
They are at present. They didn't used to be; in the (now fairly
distant) past, the equivalent of the first was simply:
int init=0 ;
for ( ; condition ; increment )
statement ;
I don't think that there was even an implicit {...} around the
statement, and there certainly wasn't one around the for
itself; any variables declared in the initialization part had a
lifetime corresponding to that of the block surrounding the for.
And code like:
for ( int i = 0 ; i < last && ! condition ; i ++ ) {
}
return i ;
was quite frequent.
The fact that "statement" had a scope until the end of the block
is an obvious oversight, since it cannot be made to work. It
was fixed very, very early. At more or less the same time, the
committee considered the possibility of reducing the scope of a
variable declared in the initialization part of a for. The
consensus at the time was, I think, that while it would be
cleaner, there was to much code in existence like the example
immediately above, which would break, and that such a change
would be irresponsible.
Much, much later---as part of the dynamic_cast proposal---the
possibility of defining a variable in a "condition" (if, while
or second part of a for) was introduced. After that, it was
felt that having different scopes for two variables, both
defined in a for loop, was too counter-intuitive, so the scope
of the variable in the initialization part of the for loop was
changed. (Responsibility wasn't an "in" word in the committee
at that point in time. IMHO, being able to declare a variable
in a condition is, itself, a mis-feature, but since no one is
required to use it, it doesn't bother me too much. Breaking
existing code did, but there wasn't much I could do about it.)
This change was fairly late in the standards proceedings; just
before CD1, I think. Many compilers didn't implement it
immediately, probably to avoid breaking existing code. Even
today, most compilers have an option to use the old for scope,
precisely so that old code can compile.
Note that the change can silently change the semantics of a
program. Consider:
static int i = 2 ;
int
f( int n )
{
for ( int i = 0 ; i < n ; ++ i ) {
}
return i ;
}
f(10) will return 10 under the old rules, 2 under the new. In
practice, I doubt that this is ever a problem in well written
code, since you normally wouldn't give a variable in local scope
the same name as one with namespace (or class) scope. (A good
general rule is that the length of a name is inversely
proportional to its visibility. Local variables, particularly
loop control variables, can have very, very short names, like i,
where as anything visible outside a single function requires a
somewhat longer, more meaningful name.)
FWIW: the version of g++ that I have on my machine (4.1.2) will
issue a warning for this code, by default (and use the new
rule). It also has an option (-fno-for-scope) to silently use
the old rule. (I had thought that -ffor-scope would turn off
the warning, but it doesn't seem to.)
Also, I believe that VC++ 6.0 (still widely used!) still
implemented the old rule---it did appear before the standard was
adopted.
--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34