Skip to content
C++ Better Explained
Go back
C++ static Keyword: What It Does in Each Context
Edit page

C++ static Keyword: What It Does in Each Context

The static keyword in C++ is one of those words that means different things depending on where you use it. This often confuses beginners — but there’s a pattern: static always either extends lifetime or restricts visibility.

Here are all four contexts with examples.


1. Static Local Variables (Extended Lifetime)

A regular local variable is created when the function is called and destroyed when it returns. A static local variable is different: it’s initialized once and persists for the entire program lifetime.

#include <iostream>
using namespace std;

void counter() {
    static int count = 0;  // Initialized only on first call
    count++;
    cout << "Called " << count << " times\n";
}

int main() {
    counter();  // Called 1 times
    counter();  // Called 2 times
    counter();  // Called 3 times
    return 0;
}

count is initialized to 0 on the first call to counter(). On subsequent calls, count already exists and keeps its value — so it keeps incrementing.

Common use: generating unique IDs

int generateID() {
    static int nextID = 1;
    return nextID++;  // Returns 1, 2, 3, 4... on each call
}

2. Static Class Members (Shared Across Instances)

A normal class member is created for each object. A static class member is shared — one copy exists regardless of how many objects you create.

#include <iostream>
using namespace std;

class Dog {
public:
    static int totalDogs;  // Declared inside class
    string name;

    Dog(string n) : name(n) {
        totalDogs++;
    }
    ~Dog() {
        totalDogs--;
    }
};

// Must be DEFINED outside the class:
int Dog::totalDogs = 0;

int main() {
    cout << Dog::totalDogs << "\n";  // 0 — no dogs yet
    {
        Dog a("Rex"), b("Max"), c("Buddy");
        cout << Dog::totalDogs << "\n";  // 3
    }  // Destructors called here
    cout << Dog::totalDogs << "\n";  // 0
    return 0;
}

Notice: Dog::totalDogs is accessed with the class name, not through an object. You can also access it through an object (a.totalDogs) but it’s the same variable.


3. Static Member Functions

A static member function belongs to the class, not to any instance. It can’t access this or non-static members:

class MathUtils {
public:
    static double square(double x) {
        return x * x;
    }

    static double cube(double x) {
        return x * x * x;
    }
};

// Call without creating an object:
cout << MathUtils::square(4);  // 16
cout << MathUtils::cube(3);    // 27

When to use static member functions:


4. Static at File Scope (Internal Linkage)

A static global variable or function is visible only within the .cpp file where it’s defined — other files can’t access it even if they’re compiled together.

// file1.cpp
static int counter = 0;           // Only visible in file1.cpp
static void helper() { /* ... */ } // Only visible in file1.cpp

void publicFunction() {           // Visible everywhere (no static)
    counter++;
    helper();
}
// file2.cpp
extern int counter;  // Error — counter doesn't exist externally

This is a way to keep implementation details private at the file level. Modern C++ prefers anonymous namespaces for this (they do the same thing in a more explicit way):

// file1.cpp
namespace {
    int counter = 0;    // Internal linkage — same effect as static
    void helper() {}
}
If you're looking to go deeper with C++, the C++ Better Explained Ebook is perfect for you — whether you're a complete beginner or looking to solidify your understanding. Just $19.

The Singleton Pattern

Static members enable the singleton pattern (one instance of a class globally):

class Config {
    Config() {}  // Private constructor — can't create externally

public:
    static Config& getInstance() {
        static Config instance;  // Created once, on first call
        return instance;
    }

    string logFile = "app.log";
    int timeout = 30;
};

int main() {
    Config& cfg = Config::getInstance();
    cfg.timeout = 60;

    Config& same = Config::getInstance();  // Same object!
    cout << same.timeout;  // 60
}

The static Config instance inside the function is a static local — created once, destroyed when the program ends.


Summary: Four Uses of static

ContextWhat it does
Local variableRetains value between function calls; initialized once
Class member variableOne shared copy for all instances; accessed as Class::member
Class member functionCan be called without an object; no this pointer
File scope (global)Restricts visibility to current translation unit (internal linkage)

The underlying theme: static either extends the lifetime (local variables, class members live as long as the program) or restricts the scope (file-scope static is invisible to other files).



Take Your C++ Further

If you’re looking to go deeper with C++, the C++ Better Explained Ebook is perfect for you — whether you’re a complete beginner or looking to solidify your understanding. Just $19.

👉 Get the C++ Better Explained Ebook — $19

📋

Free Download: The 10 Mistakes Every C++ Beginner Makes

A free 1-page checklist that shows the exact traps that slow down every C++ beginner — so you can avoid them from day one.

🔒 No spam. Unsubscribe anytime.


Edit page
Share this post on:

Previous Post
C++ Stack vs Heap Memory: What's the Difference?
Next Post
C++ Struct vs Class: What's the Difference?