The scope resolution operator ::
can be used to access a global variable shadowed by a local declaration. How do you achieve the same for a variable declared in an enclosing scope but not global?
int main() {
int i = 10;
if (1) {
int i = 5;
std::cout << "Local i: " << i << std::endl;
std::cout << "Main's i: " << ?? << std::endl; //How to access main's i?
}
return 0;
}
I know this is bad practice. But I was just curious to know if this was possible. I reckon it's not.
An explanation of why it's not possible or how it is would be useful.
This rule finds declarations of local variables or parameters that hide a global variable. Such declarations create variables with the same name but different scopes. This makes it difficult to know which variable is actually used in an expression.
In Java, the scope of a local variable is the body of the method in which it is declared. In other words, the variable is visible in the body of the method where its declaration appears, but it is not visible on the outside the method.
In simple terms, scope of a variable is its lifetime in the program. This means that the scope of a variable is the block of code in the entire program where the variable is declared, used, and can be modified.
To access a global variable in a function, if the function has a local variable with the same name, we use the global keyword before the variable name.
This is unfortunately not possible. Compiler warning options, like -Wshadow
for GCC, can help avoiding such situations:
-Wshadow
Warn whenever a local variable or type declaration shadows another variable, parameter, type, class member (in C++), or instance variable (in Objective-C) or whenever a built-in function is shadowed. Note that in C++, the compiler warns if a local variable shadows an explicit typedef, but not if it shadows a struct/class/enum. Same as -Wshadow=global.
In your example, for instance, you'd get a warning like:
: In function '
int main()
'::7:9: error: declaration of '
i
' shadows a previous local [-Werror=shadow]7 | int i = 5; |
As @L. F. points out in a comment below, you can use references to still have access to the other i
:
#include <iostream>
int main() {
int i = 10;
if (1) {
int& nonlocal_i = i; // just before shadowing
int i = 5;
std::cout << "Local i: " << i << std::endl;
std::cout << "Main's i: " << nonlocal_i << std::endl;
}
return 0;
}
But -Wshadow
will still complain, and if you were going the extra mile to find an alternative name, you could just name the local i
differently.
Note:
As user4581301 points out in a comment, code like int& i = i;
doesn't do what you'd expect in an inner scope:
#include <iostream>
int main()
{
int i = 4;
{
int& i = i;
std::cout << i;
}
}
It tries to use the variable i
to initialize itself. In Microsoft's compiler you get a compilation error like:
error C4700: uninitialized local variable 'i' used
In GCC, if you turn all the warnings on, you get this message:
error: reference 'i' is initialized with itself [-Werror=init-self]
But it silently compiles and does the wrong thing if you don't have the warnings turned on
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With