I'm a bit confused at this situation:
#include <iostream>
void function(int origin)
{
if (origin < 0)
{
double origin = 0.3;
std::cout << origin << std::endl;
}
}
int main()
{
function(-4);
}
where it gets compiled and run successfully using VS2013 under v120 ToolSet. Isn't it wrong C++? 'Cause doing the same but just in the beginning of function it gives a compile-time error.
This is legal according to C++ standard, section 3.3.3.1:
A name declared in a block is local to that block; it has block scope. Its potential scope begins at its point of declaration and ends at the end of its block. A variable declared at block scope is a local variable.
Such redeclaration hides the origin parameter.
Cause doing the same but just in the beginning of function it gives a compile-time error.
You get an error because C++ standard explicitly disallows such redeclaration in section 3.3.3.2:
A parameter name shall not be redeclared in the outermost block of the function definition nor in the outermost block of any handler associated with a function-try-block.
The reason for this exclusion is that function parameters are local to the outer scope of the function, so having a redeclaration without another layer of braces would introduce a duplicate identifier into the same scope.
I don't mind this C++ behaviour. Sure, it can lead to bugs/oversights as you have demonstrated. But you can do this in C++
for (int i = 0; i < 4; ++i) {
for (int i = 0; i < 5; ++i) {
cout << i;
}
cout << i;
}
cout << endl;
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 5; ++j) {
cout << j;
}
cout << i;
}
and the results are identical because i is redefined in the scope of the inner for loop to be a different variable.
In other languages like C# you can't do this. It will tell you have tried to redeclare a variable of the same name in an inner scope.
I find this over-protective. When I'm cutting and pasting code with loops, it is irritating to have to redeclare i, which we all tend to use as the loop variable, to be i1, i2 etc. I invariably miss one, with cut-and-paste code, so I'm using arr[i] in an i3 loop, when I meant arr[i3] (whoops).
In production code, I agree that defensive coding means you should use different names for loop variables in the same function.
But it's nice to be able to reuse variable names in nested for loops when you're experimenting. C++ gives you that choice.
Isn't it wrong C++?
No. It's perfectly legal to redeclare an identifier, as long as it's in a different scope. In this case, the scope is the then-body of the if-statement.
It isn't ambiguous. The nearest preceding declaration will be used.
No, it is not wrong. It is a perfectly valid behavior according to the standard.
void function(int origin)
{
if (origin < 0) // scope of the first 'origin'
{
double origin = 0.3; // scope of the second 'origin' begins
// scope of the first 'origin' is interrupted
std::cout << origin << std::endl;
} //block ends, scope of the second 'origin' ends
//scope of the first 'origin' resumes
}
As tupe_cat said it is always valid to redeclare if their scopes vary. In such cases variable belonging to the inner scope will gain over the outer scope.
Related
This question already has answers here:
variable declaration within the while loop C/C++
(5 answers)
Closed 5 years ago.
Why does this code cause an infinite loop:
#include <iostream>
using namespace std;
int main() {
int y = 5;
while (y < 6) {
int y = 7;
cout << y << endl;
}
}
yet removing the "int" in the while statement makes it run once normally?
(
#include <iostream>
using namespace std;
int main() {
int y = 5;
while (y < 6) {
y = 7;
cout << y << endl;
}
}
)
In this loop:
while (y < 6) {
int y = 7;
cout << y << endl;
}
The inner y is not accessible in the condition test.
If you remove the int in the loop, you're simply assigning a new value to the variable defined outside while, thus terminating it.
Look up Scope on CppReference.
The behaviour you have observed is called shadowing.
This means that a variable is "shadowed" by another variable in an inner scope.
(iBug has already provided a link to the C++ scope rules)
The outer scope (in your case while(y < 6)) can not access the inner scope (in your case int y = 7;) and vice versa. Both have the same name, but they are completely separate variables in separate scopes.
This is a very common source for errors (you also find a lot of them here) and doesn't only happen with loops and other scope brackets, but also very often with class members. Imagine a class:
class MyClass {
int a;
public:
void getA( int a ) { return a; }
};
getA() defines a parameter a, which shadows the class member a. This is at least bad style, but even more probable a source of errors. We don't know - did you want to return the member a or did you really mean the parameter? So this should be avoided.
Here's a real life example on Stackoverflow - see my comment below the question (regarding the 3rd constructor)
Possibilities to avoid these kind of errors are:
Use highest possible compiler warnings and perhaps even warnings as errors. Compilers can warn about those kind of shadowing issues.
Use a name scheme. A common scheme is members with a m, m_ prefix, a _ suffix and the like. If the member name in the MyClass would have been m_a, this would have reduced confusion. Of course this doesn't help in your example, but it's a good idea nevertheless.
So if I initialize a variable of the same type and name within the main function the compiler will complain of the re declaration, for example:
for (int i = 0; i < 5; i++)
{
int a{5};
int a{5}; // error int a previously declared here
}
But there are no errors if I compile this instead:
for (int i = 0; i < 5; i++)
{
int a{5};
}
To my understanding, this looks as if I have initialized "int a" multiple times within the same scope which obviously would cause an error. If somebody could explain what's actually happening it would be greatly appreciated! Thanks!
You are confusing scope and lifetime, it seems.
for (int i = 0; i < 5; i++)
{
int a{5};
}
To my understanding, this looks as if I have initialized "int a"
multiple times within the same scope which obviously would cause an
error.
Why would that obviously cause an error? a is always the same variable, in every iteration of the loop. But it always points to a different object, whose lifetime begins and ends with the current iteration.
If such a thing would not work, then you could not even call the same function two times:
void f()
{
int x = 0;
}
f();
f(); // why should this be an error?
Note that this question goes far beyond g++, and even far beyond C++. Every C-derived programming language works exactly like that. At least I've never seen one which doesn't.
To my understanding, this looks as if I have initialized "int a" multiple times within the same scope
You are right about the "multiple times" part, but you are wrong about "same scope": the scope of the second int a is nested inside the outer scope, in which the first int a is declared. Hence, the second declaration is legal: it hides the outer declaration, which the language allows.
int a = 5;
cout << a << endl;
{
int a = 6;
cout << a << endl;
}
cout << a << endl;
Demo above produces this output:
5
6
5
I think your getting confused with declaring variable and initializing it
for (int i = 0; i < 5; i++)
{
int a{5}; // In this part you are declaring and initializing the variable
int a{5}; // error int a previously declared here
// same with this case as well
}
If you want to do that you can use this
for (int i = 0; i < 5; i++)
{
int a{5};
a=5; // error int a previously declared here
}
at this point int a{5} This will be the declaration of a variable and initialization of variable in the for loop scope
and a=5; and here reinitialize that particular variable in the same scope
I stumbled recently in this problem
for(int i=0,n=v.size(); i<n; i++) {
...
P2d n = ... <<<--- error here
}
the compiler was complaining about the fact that the n local variable has been already defined, despite that the open brace looks like it should start a new scope.
Indeed the standard has a special wording for this and while the code compiled fine with g++4.6.3, it complains with more recent versions and other compilers.
What is the rationale (if there is any) behind this special rule?
To be more clear: the standard explains that this is not permitted and I've no questions about the technical reason for which that's an error: I was just wondering why the committee decided to use special extra rules instead of just creating another nested scope when seeing the opening brace (like it happens in other places).
For example to make the code legal you can just wrap the body with two brace pairs instead of one...
Please also note that braces after for/while/if, while considered good practice, are not mandatory and not part of the syntax, but still a scope containing the loop variables exists (therefore using function definition as another example where the scope of the locals is the body of the function is not relevant: a function body is not a statement and braces are mandatory).
In the C++ syntax the body of a for is just a statement; however if this statement happens to be a braced group then it gets a special handling in for/while/if (that doesn't happen when you use a braced group as statement elsewhere in the language).
What is the reason for adding this extra complication to the language? It's apparently not needed and just treating the braces as another inner scope seems (to me) simpler.
Are there use cases in which this simpler and more regular approach doesn't work?
Note that I'm not asking opinions. Either you know why the committee took this decision (requiring also a quite elaborate wording in the standard instead of just having the body as a regular statement with the regular handling of a brace enclosed block when used as statement) or you don't.
EDIT
The "single scope" view for the syntax is for me unnatural but technically possible for the for statement that can be rationalized as a single block with a backward goto statement, but it's hard to defend in a very similar case for the if statement:
if (int x = whatever()) {
int x = 3; // Illegal
} else {
int x = 4; // Illegal here too
}
but this is instead legal
if (int x = whatever()) {
int z = foo();
} else {
int z = bar();
}
So are the condition, the then part and the else part of an if statement the same scope? No because you can declare two z variables. Are they separate scopes? No because you cannot declare x.
The only rationalization I can see is that the then and else part are indeed separate scopes, but with the added (strange) rule that the variable declared in the condition cannot be declared in the scope. Why this extra strange limitation rule is present is what I'm asking about.
int i = 0;
for (MyObject o1; i<10; i++) {
MyObject o2;
}
Can be translated from the point view of recent compilers into:
int i = 0;
{
MyObject o1;
Label0:
MyObject o2; //o2 will be destroyed and reconstructed 10 times, while being with the same scope as o1
i++;
if (i < 10)
goto Label0;
}
This is the answer to your last question mark at the end, they didn't add something complicated, just used goto to label in the same scope, and not goto to out of the scope and then enter to it again. I don't see clear reason why it's better. (While it will do some incompatibility with older codes)
The semantics are not special for the for loop! if (bool b = foo()) { } works the same. The odd one out is really a { } block on its own. That would be rather useless if it didn't introduce a new scope. So the apparent inconsistency is due to a misplaced generalization from an exceptional case.
[edit]
An alternative view would be to consider an hypothetical, optional keyword:
// Not a _conditional_ statement theoretically, but grammatically identical
always()
{
Foo();
}
This unifies the rules, and you wouldn't expect three scope (inside, intermediate,outside) here either.
[edit 2] (please don't make this a moving target to answer)
You wonder about lifetime and scopes (two different things) in
int i = 0;
for (MyObject o1; i<10; i++) {
MyObject o2;
}
Let's generalize that:
MyObject o2; // Outer scope
int i = 0;
for (MyObject o1; i<o1.fooCount(); i++) {
std::cout << o2.asString();
MyObject o2;
}
Clearly the call to o2.asString() refers to the outer o2, in all iterations. It's not like the inner o2 survives the loop iteration. Name lookup doesn't will use names from the outer scope when the names aren't yet defined in the inner scope - and "not yet defined" is a compile-time thing. The repeated construction and destruction of the inner o2 is a runtime thing.
Look at it this way:
A pair of braces allows you to hide variables visible inside an enclosing pair of braces (or globally):
void foo(int n)
{
// the containing block
for (int i = 0; i < n; ++i)
{
int n = 5; // allowed: n is visible inside the containing { }
int i = 5; // not allowed: i is NOT visible inside the containing { }
}
}
If you think about it this way you realize there are no special rules here.
The brackets ({}) deliminate a section of code as a block. Everything in this block is within it's own local scope:
int main(int argc, char** argv)
{
int a = 5;
std::cout<<a<<std::endl // 5
{
int a = 10;
std::cout<<a<<std::endl //10
}
std::cout<<a<<std::endl // 5
}
But wait, there is something else in that code...
int main(int argc, char** argv)
{
}
This is similar to the structure of a for loop:
for (int i = 0 ; i < 5; i++)
{
}
The function definition has code outside the {...} block too!
in this case, argc and argv are defined, and they are local to the scope of the function just like the definition of i in the above for loop.
In fact you can generalise the syntax to:
definition { expression }
Where the entirety of the above is within the scope.
In this case, the 'raw' brackets ({}) form the same structure but with an empty definition statement.
edit:
to answer your edit, in:
int i = 0;
for (MyObject o1; i<10; i++) {
MyObject o2;
}
the constructor for o2 is looped over for each loop, while the the constructor for o1 isn't.
for loop behavior goes as follows (where XXX is the current block being executed:
init
for(XXX; ; ){ }
test loop exp
for( ;XXX; ){ }
execute block
for( ; ; ){XXX}
final operation
for( ; ;XXX){ }
Back to 2.
As there is there was the c tag I would answer from that perspective. Here is an example:
#include <stdio.h>
int main(void) {
int a[] = {1, 2, 3, 4, 5, 6, 7, 8};
for (int i = 0, n = 8; i < n; i++) {
int n = 100;
printf("%d %d\n", n, a[i]);
}
return 0;
}
It compiles without issues, see it working at ideone (C99 strict mode, 4.8.1).
C standard is clear that both scopes are considered as separate, N1570 6.8.5/p5 (emphasis mine):
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.
There is a warning, but only with the -Wshadow option, as expected:
$ gcc -std=c99 -pedantic -Wall -Wextra -Wshadow check.c
check.c: In function ‘main’:
check.c:7: warning: declaration of ‘n’ shadows a previous local
check.c:6: warning: shadowed declaration is here
The loop control variables (i and n in this case) are considered part of the for loop.
And since they are already declared in the loop's initialization statement, most attempts (other than re-defining by using nested braces) to re-define them within the loop results in an error!
I cannot tell you why there is just one scope opened by the for loop, not a second one due to the braces. But I can say what was given back then as the reason for changing where that single scope is: Locality. Take this kind of pretty standard code:
void foo(int n) {
int s=0;
for (int i=0; i<n; ++i) {
s += global[i];
}
// ... more code ...
for (int i=0; i<n; ++i) {
global[i]--;
}
}
Under the old rules, that would have been illegal code, defining i twice in the same scope, the function. (In C back then, it was even illegal because you had to declare variables at the beginning of the block.)
That usually meant you’d leave out the declaration in the second loop – and run into problems if the code with the first loop was removed. And whatever you did, you had variables with a long time to live, which as usual makes reasoning about your code harder. (That was before everyone and their brother started to consider ten lines a long function.) Changing for to start its own scope before the variable declaration here made code much easier to maintain.
You problem is that the definition part of the for is considered inside the scope of the for.
// V one definition
for(int i=0,n=v.size(); i<n; i++) {
...
// V second definition
P2d n = ... <<<--- error here
}
#include <iostream>
using namespace std;
int x=24 ;
int main()
{
int x=0;
{
int x=5 ;
::x= x+2 ;
}
cout<<::x<<endl ;//first
cout<<x<<endl ; // second
return 0;
}
in this simple example i'm using code block and i know i can modify the global variables using Scope resolution operator.
and i modify the global variable in this example but i wonder if there is a way to modify the variables in specific scope like main function (not necessary the( Scope resolution operator) way )
that mean in this example i need the first output is 24 and the next one 7 .
sorry for my english i hope to understand the question
There are no means to access variables from a specific scope in C++.
If you declare an object or a variable in the inner scope with the same name as an object or a variable in the outer scope, then for all intents and purposes that outer scope's object or variable is not directly visible in the inner scope.
If you already have a pointer or a reference to the outer scope's object, of course, you can still access it indirectly. You just cannot access it directly.
This is a fundamental concept of C and C++; but many other programming languages share the same analogous concept.
The scoping rules of C++ are textual and AFAIK you can't do this, as you can't go putting namespaces inside of functions. But introducing a reference with a unique name may help you as a workaround if you find yourself in a bind like this:
#include <iostream>
using namespace std;
int x = 24;
int main()
{
int x = 0;
int & main_outer_x = x;
{
int x = 5;
main_outer_x = x + 2;
}
cout << ::x << endl; //first
cout << x << endl; // second
return 0;
}
That gives you:
24
7
That shouldn't cost any more memory in your generated code, and lets you keep the outer name untouched. Still, likely to be confusing and error prone if you're purposefully having a name collision within a function. This is abstract code so it's hard to criticize, but most concrete code with such a pattern should probably be done another way.
Alright, I'm guessing this is an easy question, so I'll take the knocks, but I'm not finding what I need on google or SO. I'd like to create an array in one place, and populate it inside a different function.
I define a function:
void someFunction(double results[])
{
for (int i = 0; i<100; ++i)
{
for (int n = 0; n<16; ++n) //note this iteration limit
{
results[n] += i * n;
}
}
}
That's an approximation to what my code is doing, but regardless, shouldn't be running into any overflow or out of bounds issues or anything. I generate an array:
double result[16];
for(int i = 0; i<16; i++)
{
result[i] = -1;
}
then I want to pass it to someFunction
someFunction(result);
When I set breakpoints and step through the code, upon entering someFunction, results is set to the same address as result, and the value there is -1.000000 as expected. However, when I start iterating through the loop, results[n] doesn't seem to resolve to *(results+n) or *(results+n*sizeof(double)), it just seems to resolve to *(results). What I end up with is that instead of populating my result array, I just get one value. What am I doing wrong?
EDIT
Oh fun, I have a typo: it wasn't void someFunction(double results[]). It was:
void someFunction(double result[])...
So perhaps this is turning into a scoping question. If my double result[16] array is defined in a main.cpp, and someFunction is defined in a Utils.h file that's included by the main.cpp, does the result variable in someFunction then wreak havoc on the result array in main?
EDIT 2:
#gf, in the process of trying to reproduce this problem with a fresh project, the original project "magically" started working.
I don't know how to explain it, as nothing changed, but I'm pretty sure of what I saw - my original description of the issue was pretty clear, so I don't think I was hallucinating. I appreciate the time and answers...sorry for wasting your time. I'll update again if it happens again, but for the meantime, I think I'm in the clear. Thanks again.
Just a point about the variable scope part of the question - there is no issue of variable scope here. result/results in your someFunction definition is a parameter -> it will take on the value passed in. There is no relation between variables in a called function and it's caller -> the variables in the caller function are unknown to the called function unless passed in. Also, variable scoping issues do not occur between routines in C++ because there are no nested routines. The following pieces of code would demonstrate scoping issues:
int i = 0;
{
int i = 0;
i = 5; //changes the second i, not the first.
//The first is aliased by the second i defined first.
}
i = 5; //now changes the first i; the inner block is gone and so is its local i
so if C++ did have nested routines, this would cause variable scoping
void main()
{
double results[16];
double blah[16];
doSomething(blah);
void doSomething(double * results)
{
//blah doing something here uses our parameter results,
//which refers to blah, but not to the results in the higher scope.
//The results in the higher scope is hidden.
}
}
void someFunction(double results[])
should be exactly equivalent to
void someFunction(double *results)
Try using the alternative declaration and see if the problem persists.
To me it seems that your code should simply work.
I just tried this in g++ and worked fine. I guess your problem is elsewhere? have you tried the snipped you posted?
#include <iostream>
void someFunction(double results[])
{
for (int i = 0; i<100; ++i)
{
for (int n = 0; n<16; ++n) //note this iteration limit
{
results[n] += i * n;
}
}
}
int main()
{
double result[16];
for(int i = 0; i<16; i++)
{
result[i] = -1;
}
someFunction(result);
for(int i = 0; i<16; i++)
std::cerr << result[i] << " ";
std::cerr << std::endl;
}
Have you perhaps double defined your results array in a couple places and then accidently refered to one copy in one place and another copy elsewhere? Perhaps the second is a pointer and not an array and that is why the debugger is confused?
To ensure this problem doesn't occur, you should never use global variables like that. If you absolutely must have one, put it in a namespace for clarity.