Unraveling C++ static: From Variables to Destruction Order
This article explains the many roles of the C++ static keyword—how it affects variables, functions and class members—then dives deep into static object lifetimes, destructor rules, destruction order across translation units, common pitfalls such as resource‑dependency bugs, memory leaks and multithreading issues, and finally offers practical solutions and interview‑style questions.
1. Overview of the static keyword
In C++ the static specifier can be applied to variables, functions and class members, giving them static storage duration, internal linkage or class‑wide sharing.
1.1 Static variables
Static local variables retain their value between function calls, e.g.:
void countFunctionCalls() {
static int callCount = 0;
++callCount;
std::cout << "called " << callCount << " times
";
}Static global variables are limited to the translation unit, preventing name clashes.
Static class members are shared by all objects of the class and must be defined outside the class.
class MyClass {
public:
static int sharedValue;
};
int MyClass::sharedValue = 0;2. Static destructors – principles and rules
A destructor runs when an object’s lifetime ends, releasing resources. Static objects (both global and local) are destroyed when the program terminates, in the reverse order of their construction.
2.1 When are destructors called?
Local objects – at the end of their scope.
Static local and global objects – at program exit.
Dynamically allocated objects – when delete is executed.
2.2 Characteristics of destructors
Destructors have no parameters, no return type, and a class can have only one. The compiler generates a default one if none is provided.
2.3 Destruction order of static objects
Within a single translation unit, static objects are destroyed in the opposite order of construction. Across multiple files the order is undefined, which can cause resource‑dependency bugs.
3. Common pitfalls
Incorrect order leading to use‑after‑free (e.g., OceanBase session object accessing an already‑destroyed allocator).
Memory leaks when a static pointer owns dynamic memory but the destructor does not free it.
Data races in multithreaded code that modifies a static variable without synchronization.
4. Solutions
Force construction order by accessing dependent static objects early.
Use smart pointers ( std::unique_ptr, std::shared_ptr) to manage dynamic resources.
Protect static data with std::mutex or thread‑local storage.
5. Interview questions
Typical questions cover destruction order of global vs. local static objects, behavior in multi‑file programs, and the effect of atexit registration.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Deepin Linux
Research areas: Windows & Linux platforms, C/C++ backend development, embedded systems and Linux kernel, etc.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
