The Many Meanings of the C++ “Static” Keyword

In C++, the static keyword has a lot of meanings. Let’s go over all of them:

Meaning 1: Private Linkage

This one comes from C, and it lets you mark a variable as “file private”.

Example:

static int i = 42;
void doSomething()
{
    cout << i;
}

In this example, static tells the compiler to not make the variable i available from other source files. If another file tries to use i, perhaps using the extern keyword, it would generate a linker error (unresolved external symbol). The same concept applies to functions whose access you want to limit to the current file.

Uses:

This is very handy for creating “file private” variables and functions. I recommend using static for any file-only functions. This way, you can name them whatever you like without risking a naming collision in the global namespace.

Gotchas:

Unfortunately, you can’t declare a class as static. Also, the language makes no guarantee about the order in which static variables are initialized. In my experience, static variables in the same file are initialized in a “sane” order, so you can do things like this:

static int i = 42;
static int j = i + 1;

Meaning 2: Function Call Spanning

This one also comes from C, and it lets you give a function-local variable a long lifespan. Here’s an example:

Example:

void foo()
{
    static int callCount = 0;
    callCount++;
    cout << "foo has been called " << callCount << " times" << endl;
}

Uses:

it’s a great way to keep track of how many times a function has been called, so it works well for generating unique ID numbers (watch out for thread-safety!). It’s also useful to keep track of whether a function is being called for the first time ever, like this:

void foo()
{
    static bool firstTime = true;
    if(firstTime)
    {
        // Do something special here
        firstTime = false;
    }
}

Gotchas:

Static function-local variables are initialized the first time the function is called, not before. Using these kinds of variables can often make your code not thread safe and not re-entrant, so take care before using them. You can put static variables within scope blocks (like inside an if or for statement). I’m not totally sure what the implications are, and frankly I’ve never felt the need to limit the scope of a variable so aggressively.

Meaning 3: Per-Class Data

When you declare a class member as static, it now belongs to the class at large, and not a particular instance.

Example:

// In the .h file:
class MyClass
{
    public:
        static int FavoriteNumber;
        static void foo();
};

// In the .cpp file (to initialize the static variable):

int MyClass::FavoriteNumber = 42;

void MyClass::foo()
{
    // can't access member variables here!
}

Uses:

It’s very common to store class-level constants this way. You can declare class functions as static as well, so they would be callable from anyone who has access to your class, even if they don’t have an instance. This is handy for helper functions. I generally like to make class functions static if they don’t need to operate on any instance data, typically for private helper functions.

Gotchas:

Static members are initialized very early in your program’s execution, before main() is even called actually. You also have no guarantee about the order in which they are initialized between classes in different files. Be careful not to initialize one static class variable from another (possibly not-yet-initialized) static class variable. Also, you can’t access instance data from this within a static class function (unless someone passes you a this pointer). Lastly, you have to initialize your static class variables in your implementation (.cpp) file. Otherwise, the compiler doesn’t know how to allocate them (see the example above).

5 comments to “The Many Meanings of the C++ “Static” Keyword”

You can leave a reply or Trackback this post.
  1. Jon Willesen says: -#1

    The C++ way of making symbols “file private” is to use an unnamed namespace. As a bonus, it works with classes and other types as well:

    namespace {
    int privateVar = 0;
    void privateFunction() {}
    class privateClass {};
    }

    // code here, outside the unnamed namespace, can access
    // items inside the unnamed namespace normally.

  2. Excellent point Jon. I didn’t know you were keeping an eye here. Great to hear from you!

  3. Thanks for “file private” static use explaining, reading books I have never understood that exactly that means. (Now opened a book and saw that realy this makes functions/classes, extern by default, visible in one file only.)

  4. This is an excellent explanation – just what I needed. Many thanks!

  5. puzzledByStaticButNotNow says: -#1

    nice explanation.

Write a Reply or Comment

Your email address will not be published.