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 variable (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)

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

  • ztime

    is this code alright?

    • Alex

      You’re close, but not quite there. Your swap function does two different jobs (swaps and prints) and doesn’t even do a full swap.

      You also have redundant code to do the printing (in two different places).

      • ztime

        >doesn’t even do a full swap
        I thought you were wrong about this for a second, but after a little bit of thinking you did make sense.

        Is my second attempt alright now?

  • Gavin

    Alex,
         I created a functioning code for the quiz, but I don’t understand why it works. Since I’m not returning x and y, why does it switch when it prints outside of the results?

    • Alex

      Returning values is only necessary if you want to pass a value from a function back to the caller. Since you don’t make any function calls here, that isn’t necessary. The x and y inside the if-statement nested block refer to the x and y declared near the top of main(), so when you swap their values, the values stay swapped even when the nested block is done.

  • Tyler Chapman

    Man that first question really got me angry. I knew exactly how to do it as I had done that on my own when I was first starting to make a calculator program. However, when I try it this time, I type in literally the exact same thing as you after 15 minutes of struggling and trying to figure out what was wrong. and it still doesn’t work. But when I actually copy and pasted it worked. I spent another 15 minutes comparing my rewrite to the copy-paste and there was literally no difference at all, even all whitespace was the same. I know this isn’t really a question or relevant at all but it’s so bizarre I had to.

  • Cyrol

    I have made two programs here, one before looking into the solution and one after looking into it.

    Before:

    After:

    The one after looking into the solution obviously isnt that far away from it.

    I really have to thank you for making these tutorials :).

  • Here for question 1.
    #include<iostream>
    using namespace std;
    int main()
    {
        int x,y;
        cout<<"enter first integer:- ";
        cin>>x;
        cout<<"enter greater integer :-";
        cin>>y;
        if(y<x)
        {
            int swap;
            swap=y;
            y=x;
            x=swap;
            cout<<"numbers not in required order\n\nafter swaping:- "<<endl;
        }
        cout<<"x= "<<x<<endl<<"y= "<<y;
    }

  • I am new to this and already finding this website helpful.
    great work admin AND GREAT MAINTENANCE.

  • Zero Cool

    This is my solution for the Quiz 1:

    io.h

    io.cpp

    main.cpp

  • ukijo

    how about this?

    • Tunacan

      I did the same thing, just made a function and added a bonus feature where if the user enter 2 numbers as the same it will say "Both values are the same!"

    • Zero Cool

      Your code is right but the idea is to use variable scope to do a swap. For that you should override the variables content if it’s necesary

  • My dear c++ Teacher,
    Please let me point out that in the solution program of first quiz you use "if" statement though you cover it in a later lesson (5.2).
    With regards and friendship.

    • Alex

      I introduce “if statements” in the lesson on boolean variables. That introduction should be enough to progress past these lessons.

  • My dear c++ Teacher,
    Please let me say that if you add "#include <iostream>" in 5th program it could help beginners.
    With regards and friendship.

  • My dear c++ Teacher,
    Please let me say that first program in "Shadowing" subsection outputs 105, and second, 1010. Obviously std::endl is needed.
    With regards and friendship.

  • My dear c++ Teacher,
    Please let me ask what I can not understand. In 4th snippet (program), only variable x is referred in comments, except in line 17 where both variables x and y are referred. What do you mean?
    With regards and friendship.

  • Piyush Agrawal

    This code compiled and executed successfully, but just wanted you to take a peek at it, is it 100% accurate?

    Also could I have used void instead of int compare_values()? Code isn’t throwing an error with int even if no value is ‘returned’.

    • Alex

      A few thoughts: It’s kind of silly to introduce temporary value i just to swap x and y when your print statements are inside the else block. In that case, you might as well keep x and y as they are, and print “the smaller value is” y instead of x. Swapping becomes necessary if you move the print statements outside of the if and else blocks.

      And yes, your function should return a void since you aren’t returning a value.

  • AMG

    Alex,
    Would like to suggest to modify one of your example to show a local variable is not accessible and not destroyed.
    int a = 5;
    int b = 6;
    {
        float local_x = 7.f;
        int local_res_1 = x * add(a,b); // local variable x is not accessible inside of add and not destroyed
        int local_res_2 = x / add(a,b); // local variable x is not accessible inside of add and not destroyed
    }

  • James Ray

    Hi Alex, thanks for creating this site, it’s very useful. You say: "Then we declare a different variables" (CTRL+F to find where it says that). I think you mean: "Then we declare a different variable".

  • Petross404

    Hey Alex, that article made clear to me how variables should be defined.

    Forgive me if my question touches (and) another topic, but I recently read on stackoverflow that if I define something like:

    it get’s out of scope, the moment a right bracket (}) is reached. It also mentioned that if I define a variable like:

    I can access it just before I

    it, but this doesn’t work!

    So is there a way to access var outside the block that contains it’s definition with new operator, or is it *impossible* to ever do such a thing in C++ (hence the "rare case to define well before the first use")? Did I misinterperted what I read[1]?

    [1] http://stackoverflow.com/questions/6337294/creating-an-object-with-or-without-new (The first answer)
    "The second creates an object with dynamic storage duration and allows two things:

    Fine control over the lifetime of the object, since it **does not go out of scope automatically**; you must destroy it explicitly using the keyword delete;"

    • Alex

      > I recently read on stackoverflow that if I define something like:

      it get’s out of scope, the moment a right bracket (}) is reached

      This is trying to describe the concept of “block scope”. It’s close but not quite precise enough. This is only true if that right bracket closes the block that the variable was defined in. Closing brackets of nested blocks or called functions don’t matter in this context.

      > It also mentioned that if I define a variable like:

      I can access it just before I

      it, but this doesn’t work!

      This is called dynamic memory allocation, and I talk a lot about this in chapter 6. With dynamic memory allocation, the variable itself (var) is subject to the same limitations. But the memory allocated to hold the value isn’t automatically destroyed (even when the name var is). The same is true for static variables, which I talk more about later in this chapter.

      > So is there a way to access var outside the block that contains it’s definition with new operator, or is it *impossible* to ever do such a thing in C++

      No, there’s no way to _directly_ access variable var outside the block that contains its definition. However, there _are_ ways to indirectly access the _value_ that var had (via pointers or references), in the case where var was defined as static or dynamically.

  • Eric

    Alex,

    You need to switch your cout to std::cout in the first example under the heading "Variables should be defined in the most limited scope possible".

    Thanks again for all the time and effort you put into this site.  I can honestly say that my coding has improved thanks to your tutorials.

Leave a Comment

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