Redeclaration of a variable in a for-loop in C++

时光怂恿深爱的人放手 提交于 2019-11-30 08:28:10

The standard is somewhat ambiguous. The code you quote as being equivalent to a while loop implies that there is an inner scope where declarations inside the loop could hide declarations in the condition; however the standard also says (quoting C++11, since I don't have C++03 handy):

6.4/2 The rules for conditions apply both to selection-statements and to the for and while statements

6.4/3 If the name is re-declared in the outermost block of a substatement controlled by the condition, the declaration that re-declares the name is ill-formed.

6.5.3/1 names declared in the for-init-statement are in the same declarative-region as those declared in the condition

which between them imply that the names can't be redeclared.

Older (pre-1998) versions of the language put declarations in the for-init-statement into the declarative region outside the loop. This meant that your code would be valid, but this wouldn't:

for (int i = ...; ...; ...) {...}
for (int i = ...; ...; ...) {...}  // error: redeclaration of i

I think the code is correct. IMO, the issue is with the braces. Note that the for statement is defined as:

for ( for-init-statement; condition; expression ) statement

The loop body does not have braces, they are added when using a compound statement. But a compound statement adds its own declarative region, so the inner declaration should not have a conflict with the for-init-statement.

The following code compiles ok with clang and G++ (note the double braces):

for (int *it = a1, *end = a1+1; it != end; ++it) {{
    //...
    bool *jt = a2, *end = a2+1;
    //...
}}

My guess is that the clang compiler tries to optimize as if the loop were defined as:

for ( for-init-statement; condition; expression ) { statement-seq }

With the suble change in meaning: both declarative regions are fused together.

On second though, even it no braces are used at all:

for (int x=0; ;)
    char x;

It should compile correctly. From C++ draft 6.5, par. 2:

The substatement in an iteration-statement implicitly defines a block scope.

So the char x; by itself defines (implicitly) a block scope, and no conflicting declarations should happen.

The current version of the standard is clear on this:

6.5 Iteration statements [stmt.iter]

2 - The substatement in an iteration-statement [e.g., a for loop] implicitly defines a block scope (3.3) which is entered and exited each time through the loop.

C has a similar rule:

6.8.5 Iteration statements

Semantics

5 - An iteration statement is a block whose scope is a strict subset of the scope of its enclosing block. The loop body is also a block whose scope is a strict subset of the scope of the iteration statement.

Some, generally older compiler makes variables declared in for loops visible outside the scope of the loop.

To make all the compilers behave using the newer ( and better ) way declare a macro like this:

// In older compilers, variables declared in a for loop statement
// are in the scope of the code level right outside the for loop.
// Newer compilers very sensibly limit the scope to inside the
// loop only. For compilers which don't do this, we can spoof it
// with this macro:
#ifdef FOR_LOOP_VARS_NEED_LOCAL_SCOPE
   #define for if(0); else for
#endif

Then for each compiler that has the older behavior define FOR_LOOP_VARS_NEED_LOCAL_SCOPE. For example here is how you would do it for MSVC < 8:

#ifdef _MSC_VER
   #if _MSC_VER < 1400   //  earlier than MSVC8
      #define FOR_LOOP_VARS_NEED_LOCAL_SCOPE
   #endif
#endif

I'm a bit late to the party here, but I think this is disallowed most clearly by this passage in the C++11 standard:

3.3.3 Block scope [basic.scope.local]

4 - Names declared in the for-init-statement, the for-range-declaration, and in the condition of if, while, for, and switch statements are local to the if, while, for, or switch statement (including the controlled statement), and shall not be redeclared in a subsequent condition of that statement nor in the outermost block (or, for the if statement, any of the outermost blocks) of the controlled statement; see 6.4.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!