12.13 — Static member variables

Review of static keyword uses

In the lesson on file scope and the static keyword, you learned that static variables keep their values and are not destroyed even after they go out of scope. For example:

This program prints:


Note that s_id has kept its value across multiple function calls.

The static keyword has another meaning when applied to global variables -- it gives them internal linkage (which restricts them from being seen/used outside of the file they are defined in). Because global variables are typically avoided, the static keyword is not often used in this capacity.

Static member variables

C++ introduces two more uses for the static keyword when applied to classes: static member variables, and static member functions. Fortunately, these uses are fairly straightforward. We’ll talk about static member variables in this lesson, and static member functions in the next.

Before we go into the static keyword as applied to member variables, first consider the following class:

When we instantiate a class object, each object gets its own copy of all normal member variables. In this case, because we have declared two Something class objects, we end up with two copies of m_value: first.m_value, and second.m_value. first.m_value is distinct from second.m_value. Consequently, the program above prints:


Member variables of a class can be made static by using the static keyword. Unlike normal member variables, static member variables are shared by all objects of the class. Consider the following program, similar to the above:

This program produces the following output:


Because s_value is a static member variable, s_value is shared between all objects of the class. Consequently, first.s_value is the same variable as second.s_value. The above program shows that the value we set using first can be accessed using second!

Static members are not associated with class objects

Although you can access static members through objects of the class (as shown with first.s_value and second.s_value in the example above), it turns out that static members exist even if no objects of the class have been instantiated! Much like global variables, they are created when the program starts, and destroyed when the program ends.

Consequently, it is better to think of static members as belonging to the class itself, not to the objects of the class. Because s_value exists independently of any class objects, it can be accessed directly using the class name and the scope resolution operator (in this case, Something::s_value):

In the above snippet, s_value is referenced by class name rather than through an object. Note that we have not even instantiated an object of type Something, but we are still able to access and use Something::s_value. This is the preferred method for accessing static members.

Defining and initializing static member variables

When we declare a static member variable inside a class, we’re telling the compiler about the existence of a static member variable, but not actually defining it (much like a forward declaration). Because static member variables are not part of the individual class objects (they are treated similarly to global variables, and get initialized when the program starts), you must explicitly define the static member outside of the class, in the global scope.

In the example above, we do so via this line:

This line serves two purposes: it instantiates the static member variable (just like a global variable), and optionally initializes it. In this case, we’re providing the initialization value 1. If no initializer is provided, C++ initializes the value to 0.

Note that this static member definition is not subject to access controls: you can define and initialize the value even if it’s declared as private (or protected) in the class.

If the class is defined in a .h file, the static member definition is usually placed in the associated code file for the class (e.g. Something.cpp). If the class is defined in a .cpp file, the static member definition is usually placed directly underneath the class. Do not put the static member definition in a header file (much like a global variable, if that header file gets included more than once, you’ll end up with multiple definitions, which will cause a linker error).

Inline initialization of static member variables

There are a few shortcuts to the above. First, when the static member is a const integral type (which includes char and bool) or a const enum, the static member can be initialized inside the class definition:

In the above example, because the static member variable is a const int, no explicit definition line is needed.

Second, static constexpr members can be initialized inside the class definition:

An example of static member variables

Why use static variables inside classes? One great example is to assign a unique ID to every instance of the class. Here’s an example of that:

This program prints:


Because s_idGenerator is shared by all Something objects, when a new Something object is created, the constructor grabs the current value out of s_idGenerator and then increments the value for the next object. This guarantees that each instantiated Something object receives a unique id (incremented in the order of creation). This can really help when debugging multiple items in an array, as it provides a way to tell multiple objects of the same class type apart!

Static member variables can also be useful when the class needs to utilize an internal lookup table (e.g. an array used to store a set of pre-calculated values). By making the lookup table static, only one copy exists for all objects, rather than making a copy for each object instantiated. This can save substantial amounts of memory.

12.14 -- Static member functions
12.12 -- Const class objects and member functions

180 comments to 12.13 — Static member variables

  • Lesommeil

    Do not put the static member definition in a header file (much like a global variable, if that header file gets included more than once, you’ll end up with multiple definitions, which will cause a compile error).
    >Are not multiple definitions are linker error?

  • cjames

    Something::s_idGenerator is copy-initialized on line 15 of the last example. Doesn't make much of a difference since it's an integer anyways, but you might want to make it consistent with the other initializations.

  • Sayyad Mohammad Hassan

    Every thing is absolutely right and good on this site but I am getting confused to understand the word 'instantiate' according to the sentences.

    • Alex

      Instantiate means to create an object (or in the case of templates, a function or class).

      For example:

  • Jone

    What differences between const and static  please explain with example

    • Bigom

      Const means NO ONE CAN MODIFY it after instantitating it.
      Static means EVERYONE CAN USE it

      • cjames

        Not quite. Static (in this context) means the object has static storage duration. That is, it is instantiated when the program begins, and destroyed when it ends.

  • Andrew Johnson

    @Nascardriver: I'm getting emails that you are responding to my comments, but I can never see them.  Seems a bit strange as I can see someone else's comment.

  • Andrew Johnson

    [It doesn't appear that my first posting of this question was captured so apologies if it actually appears twice!]
    In an earlier lesson on constants it was stated that with C++17, we should use "inline constexpr".  When I write the following code, I get a compiler error that "the variables are defined as inline":

    If I change the variable declaration to use static, it compiles fine:

    Thinking about it, those constants should be static - i.e. applicable for instances of the class - but despite googling, I can't find any understandable reason why "inline constexpr" doesn't work.  In fact, the whole "inline constexpr" confuses me - can someone explain it a little more please, and also why it doesn't work in this particular case.

    • michael oska

      make sure your cmake file is set to version 17 or higher,inline work fine for me even your code doesn t give me any error, don t know if i m missing somehting
      as side advice put your constant in namespace

      • Andrew Johnson

        It's set up to use C++17 correctly and, yes, they need to go in a namespace, thanks.  But it doesn't like them nonetheless unfortunately.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]