Is there any way to access a local variable in outer scope in C++?
Asked Answered
F

5

22

Just out of curiosity: if I have nested scopes, like in this sample C++ code

using namespace std;

int v = 1; // global

int main (void)
{
    int v = 2; // local
    {
        int v = 3; // within subscope
        cout << "subscope: " << v << endl;
        // cout << "local: " << v << endl; 
        cout << "global: " << ::v << endl;
    }
    cout << "local: " << v << endl;

    cout << "global: " << ::v << endl;

}

Is there any way to access the variable v with the value 2 from the "intermediate" scope (neither global nor local)?

Flytrap answered 2/12, 2011 at 15:29 Comment(6)
This wouldn't be valid in C# anyway.Paradox
I would say that this is rather bad practice to begin with, using the same variable name in each new scope doesn't seem to be a good idea for any reason.Macaronic
no. if you need to access it rename the variables.Plotinus
@Jon - glad to hear C# doesn't allow this - I would never have tried :)Dapple
To add to Jon's point, one local v is legal, but the second v local inside main creates an issue, as another v is already in the "parent or current" scope, as the compiler message would say.Biofeedback
@JonSkeet Ok, this does not compile in C#, I didn't know it. Thanks!Flytrap
P
22

You can declare a new reference as an alias like so

int main (void)
{
    int v = 2; // local 
    int &vlocal = v;
    {
        int v = 3; // within subscope
        cout << "local: " << vlocal  << endl; 
    }
}

But I would avoid this practice this altogether. I have spent hours debugging such a construct because a variable was displayed in debugger as changed because of scope and I couldn't figure out how it got changed.

Private answered 2/12, 2011 at 15:33 Comment(2)
and the purpose of this rather than simply renaming v to vlocal would be?Gunpowder
@Gunpowder If the OP was concerned about changing some spaghetti legacy code with minimal alterationPrivate
H
9

The answer is no, you cannot.

A variable in local scope shadows the variable in global scope and the language provides a way for accessing the global variable by using qualified names of the global like you did. But C++ as an language does not provide anyway to access the intermediate scoped variable.

Considering it would have to be allowed it would require a lot of complex handling, Imagine of the situation with n number of scopes(could very well be infinite) and handling of those.

You are better off renaming your intermediate variables and using those that would be more logical and easy to maintain.

Humism answered 2/12, 2011 at 15:35 Comment(2)
What's an example where the number of scopes is infinite? Or did you just mean to say a very large number of scopes?Microampere
Imagine of the situation with n number of nested inherited member functions in a series of extended classes(could very will be infinite) and handling of those. Oh wait, there is a way of handling those. I agree that there are definitely more logical and easier to maintain ways of doing things, but your complex handling comment is pretty irrelevantMelba
T
5

There are two types of scope resolution operators in C++—unary scope and a class scope. There isn't any function scope or "any particular parent scope" resolution operators. That makes it impossible to solve your problem, as it is, in general because you cannot refer to anonymous scopes. However, you can either create an alias, rename variables, or make this a part of the class, which of course implies a code change. This is the closest I can get you without renaming in this particular case:

#include <iostream>

using namespace std;

int v = 1; // Global

class Program
{
    static int v; // Local

public:
    static int main()
    {
        int v = 3; // Within the subscope
        cout << "subscope: " << v << endl;
        cout << "local: " << Program::v << endl;
        cout << "global: " << ::v << endl;
    }
};

int Program::v = 2;

int main()
{
    return Program::main();
}

There are other ways, like making sure that variables are not optimized out and are on stack. Then you can work with stack directly to get the value of the variable you want, but let's not go that way.

Threedimensional answered 2/12, 2011 at 15:49 Comment(0)
L
2

You could fake it like this:

#include <iostream>
using namespace std;
int v = 1;

int main()
{
        int v = 2;
        {
                int &rv = v; // create a reference
                int v = 3; // then shadow it

                cout << "subscope: " << v << endl;
                cout << "local: " << rv << endl;
                cout << "global: " << ::v << endl;
        }
        cout << "local: " << v << endl;

        cout << "global: " << ::v << endl;

        return 0;
}

Interestingly this compiles on cygwin g++ but segfaults if you try to run it:

#include <iostream>
using namespace std;
int v = 1;

int main()
{
        int v = 2;
        {
                int &v = v;
                cout << "subscope: " << v << endl;
                // cout << "local: " << v << endl; 
                cout << "global: " << ::v << endl;
        }
        cout << "local: " << v << endl;

        cout << "global: " << ::v << endl;

        return 0;
}
Largely answered 2/12, 2011 at 15:48 Comment(0)
R
0

You could shadow the variable after you use the one from the outer scope:

#include <iostream>

using namespace std;

int v = 1; // global

int main (void)
{
    int v = 2; // local
    {
        cout << "local: " << v << endl; 
        int v = 3; // within subscope
        cout << "subscope: " << v << endl;
        cout << "global: " << ::v << endl; 
    }
    cout << "local: " << v << endl; 

    cout << "global: " << ::v << endl; 

    return 0;
}
Rustin answered 11/12, 2023 at 0:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.