Search

6.9 — Static local variables

The term static is one of the most confusing terms in the C++ language, in large part because static has different meanings in different contexts.

In prior lessons, we covered that global variables have static duration, which means they are created when the program starts and destroyed when the program ends.

We also discussed how the static keyword gives a global identifier internal linkage, which means the identifier can only be used in the file in which it is defined.

In this lesson, we’ll explore the use of the static keyword when applied to a local variable.

Static local variables

In lesson 2.4 -- Introduction to local scope, you learned that local variable have automatic duration by default, which means they are created at the point of definition, and destroyed when the block is exited.

Using the static keyword on a local variable changes its duration from automatic duration to static duration. This means the variable is now created at the start of the program, and destroyed at the end of the program (just like a global variable). As a result, the static variable will retain its value even after it goes out of scope!

The easiest way to show the difference between automatic duration and static duration variables is by example.

Automatic duration (default):

Each time incrementAndPrint() is called, a variable named value is created and assigned the value of 1. incrementAndPrint() increments value to 2, and then prints the value of 2. When incrementAndPrint() is finished running, the variable goes out of scope and is destroyed. Consequently, this program outputs:

2
2
2

Now consider the static version of this program. The only difference between this and the above program is that we’ve changed the local variable from automatic duration to static duration by using the static keyword.

Static duration (using static keyword):

In this program, because s_value has been declared as static, s_value is created (and zero-initialized) once (at program start). The variable is then initialized with our supplied initialization value (1) the first time the variable definition is encountered (but it is not reinitialized on subsequent calls).

When s_value goes out of scope at the end of the function, it is not destroyed. Each time the function incrementAndPrint() is called, the value of s_value remains at whatever we left it at previously. Consequently, this program outputs:

2
3
4

Just like we use “g_” to prefix global variables, it’s common to use “s_” to prefix static (static duration) local variables.

One of the most common uses for static duration local variables is for unique ID generators. Imagine a program where you have many similar objects (e.g. a game where you’re being attacked by many zombies, or a simulation where you’re displaying many triangles). If you notice a defect, it can near impossible to distinguish which object is having problems. However, if each object is given a unique identifier upon creation, then it can be easier to differentiate the objects for further debugging.

Generating a unique ID number is very easy to do with a static duration local variable:

The first time this function is called, it returns 0. The second time, it returns 1. Each time it is called, it returns a number one higher than the previous time it was called. You can assign these numbers as unique IDs for your objects. Because s_itemID is a local variable, it can not be “tampered with” by other functions.

Static variables offer some of the benefit of global variables (they don’t get destroyed until the end of the program) while limiting their visibility to block scope. This makes them safe for use even if you change their values regularly.

Quiz time


Question #1

What effect does using keyword static have on a global variable? What effect does it have on a local variable?

Show Solution


6.10 -- Scope, duration, and linkage summary
Index
6.8 -- Why (non-const) global variables are evil

28 comments to 6.9 — Static local variables

  • MrFinn

    The C++ standard now defines an original and a revised meaning for the 'auto' keyword. Quote (MSDN):

    Starting with Visual C++ 2010, the auto keyword directs the compiler to deduce the type of a declared
    variable from its initialization expression. The previous meaning of the auto keyword as the specifier
    for the automatic storage-class is now an error.

    Check the MSDN for more and for compiler options to choose which behaviour you prefer.

  • Jyot

    Is there any way to use xx defined in f1.cpp

  • Jyot

    I am able to understand why i am getting
    100
    0
    instead of
    100
    111
    /****f1.cpp****/
    #include
    using namespace std;
    int xx;

    void call()
    {
    cout<<xx<<endl;

    }
    /****f2.cpp****/
    #include
    using namespace std;
    static int xx=100;
    extern void call();
    int main()
    {

    cout<<xx<<endl;
    {
    extern int xx;
    xx=111;
    call();
    }}

  • CodeChaos

    The name "file scope" is technically incorrect. It can even be misleading. For example, consider you have two files, eg.h and eg.cpp:

    eg.h

    static int myvar; //file scope!?

    eg.cpp

    #include "eg.h"
    
    int main()
    {
       myvar = 2; //this is OK. what!?
       return 0;
    }

    Since eg.h is included in eg.cpp, anything declared in eg.h as "file scope" will still be accessible in eg.cpp, even though it was in a different source file. This is because both source code files are compiled into the same object (*.o) file.

    "File scope" should really be "object scope".

  • Alex, thank you for this excellent tutorial! Great explanation of what is otherwise quite a tricky set of concepts.

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">