Search

4.1a — Local variables, scope, and duration

The following section builds on section 1.4b -- a first look at local scope.

When discussing variables, it’s useful to separate out the concepts of scope and duration. A variable’s scope determines where a variable is accessible. A variable’s duration determines where it is created and destroyed. The two concepts are often linked.

Variables defined inside a block are called local variables. Local variables have automatic duration, which means they are created (and initialized, if relevant) at the point of definition, and destroyed when the block they are defined in is exited. Local variables have block scope (also called local scope), which means they enter scope at the point of declaration and go out of scope at the end of the block that they are defined in.

Consider this simple function:

Because i and d were defined inside the block that defines the main function, they are both destroyed when main() is finished executing.

Variables defined inside nested blocks are destroyed as soon as the inner block ends:

Variables defined inside a block can only be seen within that block. Because each function has its own block, variables in one function can not be seen from another function:

This means functions can have variables or parameters with the same names as other functions. This is a good thing, because it means we don’t have to worry about naming collisions between two independent functions. In the following example, both functions have variables named x and y. These variables in each function are unaware of the existence of other variables with the same name in other functions.

Nested blocks are considered part of the outer block in which they are defined. Consequently, variables defined in the outer block can be seen inside a nested block:

Shadowing

Note that a variable inside a nested block can have the same name as a variable inside an outer block. When this happens, the nested variable “hides” the outer variable. This is called name hiding or shadowing.

If you run this program, it prints:

10
5

In the above program, we first declare a variable named apples in the outer block. Then we declare a different variables (also named apples) in the nested block. When we assign value 10 to apples, we’re assigning it to the nested block apples. After printing this value, nested block apples is destroyed, leaving outer block apples with its original value (5), which is then printed. This program executes the exact same as it would have if we’d named nested block apples something else (e.g. nbApples) and kept the names distinct (because outer block apples and nested block apples are distinct variables, they just share the same name).

Note that if the nested block apples had not been defined, the name apples in the nested block would still refer to the outer apples, so the assignment of value 10 to apples would have applied to the outer block apples:

The above program prints:

10
10

In both examples, outer block apples is not impacted by what happens to nested block apples. The only difference between the two programs is which apples the expression apples = 10 applies to.

Shadowing is something that should generally be avoided, as it is quite confusing!

Rule: Avoid using nested variables with the same names as variables in an outer block.

Variables should be defined in the most limited scope possible

For example, if a variable is only used within a nested block, it should be defined inside that nested block:

By limiting the scope of a variable, you reduce the complexity of the program because the number of active variables is reduced. Further, it makes it easier to see where variables are used. A variable defined inside a block can only be used within that block (or nested sub-blocks). This can make the program easier to understand.

If a variable is needed in an outer block, it needs to be declared in the outer block:

This is one of the rare cases where you may need to declare a variable well before its first use.

Rule: Define variables in the smallest scope possible.

Function parameters

Although function parameters are not defined inside the block belonging to the function, in most cases, they can be considered to have block scope.

The exception case is for function-level exceptions, which we’ll cover in a future section.

Summary

Variables defined inside blocks are called local variables. These variables can only be accessed inside the block in which they are defined (including nested blocks), and they are destroyed as soon as the block ends.

Define variables in the smallest scope that they are used. If a variable is only used within a nested block, define it within the nested block.

Quiz

1) Write a program that asks the user to enter two integers, the second larger than the first. If the user entered a smaller integer for the second integer, use a block and a temporary variable to swap the smaller and larger values. Then print the value of the smaller and larger variables. Add comments to your code indicating where each variable dies.

The program output should match the following:

Enter an integer: 4
Enter a larger integer: 2
Swapping the values
The smaller value is 2
The larger value is 4

2) What’s the difference between a variable’s scope and duration? By default, what kind of scope and duration do local variables have (and what do those mean)?

Quiz solutions

1) Show Solution

2) Show Solution

4.2 -- Global variables and linkage
Index
4.1 -- Blocks (compound statements)

66 comments to 4.1a — Local variables, scope, and duration

  • Philip Rueger

    Hi,

    thank you for your great tutorial! I’m loving it.

    Yet, why do the newly defined, nested larger and smaller values NOT die after the if-block? Why does their new value persist even after the if-block?

    Thanks in advance,

    Philip

    • Robert James

      The "newly defined" values that you are talking about for the values of larger and smaller don’t die after the if-statement because they are variables that are defined outside of that specific if-statement.

  • Joseph

    Did you sneak a few inuendos into this tutorial, or am I just too dirty minded haha. I read something in this lesson and remembered how I saw in a few past lessons a couple inuendos haha

  • Elpidius

    It appears that when variables are assigned another value inside a nested block, its value persists, even after the block ends. It is only a variable that has been defined inside a nested block that is destroyed at the end of the block.

    Your aforementioned example explaining ‘name hiding’ or ‘shadowing’ only prints 10 and 5 because you have initialized another variable with an identical name in a nested block, and is thereby destroyed at the end of the block. However, if you simply assign the variable, ‘apples’, another value, its value persists even after exiting the nested block.

    For example:

    This program prints:

    • Alex

      Correct.

      Variable hiding/shadowing only occurs when a variable is defined in an inner block that has the same name as a variable in an outer block.

      In your example above, this does not happen, so the name apples in the inner block refers to the variable defined in the outer block.

    • Future Cat

      Can you guys explain more, I can’t quite understand the difference between Alex’s example and Elpidius’s

      how come  apples print 5 in the first one and 10 in the second

      • Alex

        In my example, the inner block has it’s own apples variable. When the inner block refers to apples, it refers to it’s own apples, not the apples previously defined in the outer block. Thus, the inner block apples is the one that gets assigned the value 10. Outer block apples stays 5 the whole time.

        However, in Elpidius’s example, the inner block is no longer declaring a new variable named apples -- it’s simply assigning the value 10 to some variable named apples. Thus, the outer block apples is the one that gets assigned the value 10.

        • Olvin Lizama

          I was having the same question about shadowing, because in a previous quiz I made a program with a variable in a outer block and then assigned a new value in the inner block and it changed the value of the variable in the outer block and my program works, now I get it.

          As you can see, vNum is the parameter of the function makeBinary() then it’s evaluated and modified inside an inner block, for a moment I  thought my code was wrong, perhaps you could include a side note that this affects only to the variables being defined outside and inside the blocks, not the ones being assigned with a different value.

  • Horia

    can you please tell me what is wrong with my code? thanks 😀

  • techsavvy....aye

    I didn’t get the significance of

    in the program -

    And also a minor mistake of writing “are” twice in -

    Function parameters

    Although function parameters are are not defined inside the block belonging to the function, in most cases, they can be considered to have block scope.

  • Edward

    Why is the the inner block statement with the apples variable defined explicitly work.

    { // nested block
            apples = 10; // apples is assigned a new value

            std::cout << apples << "\n";
    }

    but fails if the apples variable is defined implicitly

    { // nested block
            apples(10); // variable is failing because the compiler regards it as a function

            std::cout << apples << "\n";
    }

    • Alex

      When initializing a new variable, apples(10) assigns the value 10 to variable apples. Otherwise, C++ treats apples(10) as a function call to some function named apples.

      In this case, you’re not defining variable apples (it was defined previously), so C++ treats () as a function call, not an initialization.

  • andy mackeroon

    I am having real trouble understanding something, I have added a main() to call you sample sample code:-

    But it prints 20 to the screen regardless of whether say:-

    or

    why?

    • Alex

      is essentially the same as:

      We need to do the comparison as to whether x or y is larger because either one could be larger.

  • andrew mackeroon

    Hi Alex, thanks for the reply, I think u may have missed my point, I understand what it does, but it didn’t work. Regardless of whether I passed the larger number to x or y, it always passed back the larger number, IE it always said x was larger than y regardless of whether it was or not. I spent hours on it even replacing the code with if statements like u have there, i changed the name of the variable that was returned so it was different from function, I tried everything I could think of but the function always gave the wrong result!
    the only way it worked was if i put

    but if I placed the value in a variable and returned the variable it didn’t give the correct result.

    • Alex

      I feel like I’m missing something really obvious. Looking at the code you pasted in the previous comment, it functions exactly as it should. Whether you call max(10, 20) or max(20, 10), it returns (and prints) 20.

      Are you expecting it to do something else?

      • andy mackeroon

        Aah yes I am, I guess it’s me that’s missing the point, which I assumed it was all along, lol. Looks like I have spent a day and a half in a logic black hole, obviously it doesn’t matter which way around we pass the parameter we are checking to see which is the largest and 20 is always going to be larger than 10, or at least for the foreseeable future until the laws of physics are reviewed, thanks and sorry for asking a stoopid question.

  • Prime

    Hi, the compiler keeps telling me “cout is ambiguous”. Could anybody please tell me why?
    Thanks in advance

    • Alex

      I don’t see anything wrong with this code (outside of the missing { after the if statement). Compiles fine for me.

      Try replacing all of the cout and end with std::cout and std::endl and it should resolve your issue.

  • Achsaf

    Can someone please explain to me how/why Alex’s temporary value in question 1 works?

    • Alex

      The goal in that block of code is to swap the value of smaller and larger. However, C++ doesn’t natively support a way to swap two values. So instead, we enlist the help of a third variable (named temp) to temporarily hold one of the values so that when we assign smaller to larger we don’t lose the value that was previously in larger.

      If you pick smaller = 5 and larger = 2 and then walk through each line of code, tracking the current value for larger, smaller, and temp, you should see pretty quickly how it works.

  • Jim

    Alex,
    If I’m not mistaken there are a few errors in the comments on this program. All of the "y’s" are missing. Note I’ve taken the liberty to add them below, enclosed in parentheses. Although add gets the values (5)from int x and the value (6) from int y in main both the x and y in main are separate variables from the x and y in add.

  • Jim

    Alex,

    I had trouble trying to figure out how to swap numbers and ended up coping that part from your lesson.  You should consider putting that code into one of your lesson.

    [code}
    #include <iostream>
    using namespace std;
    int main()
    {
    int small;      // small starts here
    cout << "Enter an integer ";
    cin >> small;

    int larger;     // large starts here
    cout << "Enter a larger integer ";
    cin >> larger;

    if (small > larger)
        {
        int temp = larger; //temp starts here
        larger = small;
        small = temp;      //temp destroyed
        }
    cout <<small<<" is " << "less then " <<larger <<endl;

    return 0;
    }           // small and large are destroyed
    [/code}

  • dragonosman2

    I’m having some trouble with the code I wrote for the quiz on this page. I’ll copy-paste it here to ask what I’m doing wrong.

    Note: keep_window_open() is declared in keep_window_open.h and defined in keep_window_open.cpp, and it’s a function that will wait for the user to enter a character at the keyboard before exiting after showing the program’s output.  I wrote the function to keep the window open after showing the output when running the program directly by double clicking on the .exe file.

    • Alex

      You have a logic error here:

      This is a good example for which using a debugger to step through the program and watch the values would have been appropriate.

  • dragonosman2

    Okay, I wrote this way instead (and also included the comments needed as per the specs):

    Hope this is good enough.

  • Febar

    Hi Alex,
    thanks you so much for this wonderful tutorial.
    I try to solve quiz 1 but my code doesn’t work as expected.
    Can you tell me what is wrong??

    Thank you very much.

    • shahns

      You do not return any of the swapped values. Pass by reference and make swap void.

    • Alex

      Two problems.
      1) You can’t return more than one value (“return x, y;” is not valid)
      2) The variables in function swap are passed by value, which means x is a copy of smaller and y is a copy of larger. You’re swapping the copies, not the actual variables.

      The best way to resolve this would be to make x and y reference parameters (but we haven’t covered those yet).
      The second best way would be to not use a function to do the swap for now.

  • shahns

    Alex,

    Why use the terms "non-constant variable" and "constant variable"

    A "non-constant variable" is by definition a variable

    A "constant variable" is by definition a constant.

    It just seems verbose and confusing trying to follow these defiantions.

    Thanks for these tutorials !

  • Max

    "Local variables have automatic duration, which means they are created when the block they are defined in is entered, and destroyed when that block is exited."

    Aren’t local variables created when they are declared and not when the block is entered?

    • Alex

      Yes, variables are created at the point of definition.

      • Raquib

        Hey Alex,

        So are you saying in the example above,

        if (larger < smaller)
        {                                                // temp is actually created here??
            cout << "Swapping the values" << "\n";
            int temp = larger;                           // and not HERE
            larger = smaller;
            smaller = temp;
        }                                               //temp dies here

        If yes, my question is who does that?? I mean who is responsible to allocate a memory for the variable like temp before it is even declared (before that line is executed). As it has to happen at runtime, is it like there’s a "special something(perhaps a program)" that scans through the code ahead and at every entry point of a block creates all the variables together that are used inside the block. Is it like the scanning runs ahead than the actual line being executed?? How does this work??

        I am unsure if I am able to convey my query properly.

        Thanks.

        • Alex

          I changed my answer to the comment you replied to, because upon re-read, I found it misleading.

          Your question makes sense. For now, to keep things simple, variables get created/initialized at the point of definition, and local variables die at the end of the block in which they are defined.

          I talk more about how memory allocation for variables works in lesson 7.9 -- The stack and the heap. That lesson should answer your question.

  • Jester

  • Jane Doe

    Wouldn’t you define them in variables in the largest scope in which they are used? If you are using the variable in the outer block and the inner block wouldn’t you want to define it in the largest scope (in which it is used)?

    • Alex

      I see where the point of confusion is here. I’ve updated the wording to say, “define your variables in the smallest scope possible”. Does that make it clearer what the intent of the rule is?

  • Nyap

    “Local variables have automatic duration, which means they are created when the block they are part of is entered”
    Why does this not work then? D=

    /home/nyap/Desktop/Projects/Sandbox/main.cpp|5|error: ‘watermelon’ was not declared in this scope|

    • Nyap

      is it because watermelon is defined when the block is entered, but not declared/associated with the identifier "watermelon" until line 6?

      • Alex

        Variable watermelon is not in scope until it is declared (on line 6).

        Note the difference between duration and scope. Duration controls when a variable is created and destroyed. Scope controls where it is visible/usable.

  • subh

    Hi Alex,

    I have written below code for quiz 1. The code works fine for integer inputs. But it shows irregularities when I provide any character.
    (prints "2nd number is greater" if I enter any char.
    How can I fix this, so that in case of char inputs it will show some warning messages, eg "provide only integer values"

    #include <iostream>
    int swaptwo (int a, int b);
    int main ()
    {
        using std::cout ;
        using std :: cin ;
        using std :: endl;

        cout << "Enter two numbers, second should be greater \n";
        int smaller;
        int larger;
        cin >> smaller;
        cin >> larger;

        if (smaller < larger)
        {
           cout << "2nd number is greater";
        }
        else
        {

        swaptwo(smaller, larger);
        cout << "swapped";
        }
    }

    int swaptwo (int a, int b)
    {
        using std::cout ;
        using std :: endl;
        int temp;
        temp = a;
        a =b;
        b = temp;
        cout << a << endl;
        cout << b << endl;
        return 0;

    }

  • Huiying

    #include<iostream>
    using namespace std;
    int a,b;
    void change(int&,int&);
    void change(int&x,int&y)
    {
       if (y>x)    //want smallest to largest value
        
        
        {float temp=y;
        y=x;
       x=temp;
    }

    }
    int main()
    {
        cout<<"Enter two integers"<<endl;
        cin>>a>>b;
        change(a,b);
        cout<<a<<" "<<b<<endl;
        return 0;
    }

    i used the swapping algorithm together with a pass by reference. But lets say if i have to swap three integers a,b,c from the smallest to the largest, then how would i modify the above algorithm to do it?

    • Alex

      You could do it in two ways. Either create a function that takes 3 values and:
      1) uses multiple if statements to determine how to order them.
      2) calls the 2-value version of the function to ensure the elements are swapped as appropriate.

  • bert

    The following strikes me as mixing singular/plural for variables/name/variable:

    "Note that variables inside nested blocks can have the same name as variable inside outer blocks."

    Ok, i feel like i’m pestering you but i’m so enjoying reading this that if i find something i think might be off, i hope it can be corrected for the next reader - or i can be enlightened.

    tx!

  • ech

    <code>
    #include <iostream>

    int main(){

        int i;
        int l;
        int s;

        std::cout << "Enter an integer: " << std::endl;
        std::cin >> i;
        std::cout << "Enter a larger integer" << std::endl;
        std::cin >> l;

        if (l < i){
            s = l;
            l = i;
            i = s;
        }

        std::cout << "The smaller value is " << i << std::endl;
        std::cout << "The larger value is " << l << std::endl;

        return 0;
    }
    </code>

  • Theo

    I did the solution like this Alex. Is it okay, or does it defeat the purpose of the exercise for showing the scope and duration of variables?

    int main()
    {
        std::cout << "Enter a number: " << std::endl;
        int x;
        std::cin >> x;

        std::cout << "Enter a larger number than the previous: " << std::endl;
        int y;
        std::cin >> y;
        
        if (x > y)
        {
            std::cout << "Swapping the values" << std::endl;

            std::cout << "The smaller number is: " << y << std::endl;
            std::cout << "The bigger number is: " << x << std::endl;
        }
        else
        {
            std::cout << "The smaller number is: " << x << std::endl;
            std::cout << "The bigger number is: " << y << std::endl;
        }
        return 0;
    }

  • Steeve

    now block scoping in JavaScript also makes sense…..

  • Matt

    At the end of section "Shadowing", there is a line which I think needs to be fixed:
    "In both examples, outer block apples and is not impacted by what happens to nested block apples."

    • Alex

      I had to read the sentence 4 times to figure out there was an extra “and” in there. Our brains are so weird. Thanks for pointing that out.

  • mahdi

    please answer the question
    when counter is printing, thats value is 0,whay?!!!!!!!!!

    • Alex

      Your counter variable in main is shadowing the global variable main. So while fib() is incrementing the global variable counter, main is printing the local variable counter (which is initialized to 0 and never changed).

      Remove the local variable counter and your program should work as you expected.

      • mahdi

        I removed local variable counter in main,but printing 0 likewise

        • Alex

          Ah, I see now. The short answer is that you’ve broken the golden rule of not using a variable with side effects applied more than once in a statement. Note that function fib() has the side effect of changing counter. You’re both calling fib() and printing counter() in the same statement.

          If you break the statement up into two statements:

          It will work like you expect.

  • Simon Joel

    hello, I tried to run this code but it seems the swap function doesn’t get to execute. is that because the x and y are died after the function?
    I use return, so I was expecting the function to return the x, y to the main. where did this went wrong? thank you for helping.

    • Alex

      Your function Swap() parameters x and y are copies of main’s x and y variables. Thus, when you modify Swap’s x and y, you’re just modifying copies. Returning “x,y” just returns y, and your main function is discarding this result anyway.

      For now, just do your swap inline as part of main(). The best way to write a swap function is to use reference parameters, which is a concept we cover in chapters 6 and 7.

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter