[2026] C++ Zero Initialization | The All Bits Zero First Step
이 글의 핵심
Zero initialization sets storage to zero. Static and thread-local objects get it before dynamic init; locals do not unless you value-initialize. Relation to value and default init.
What is zero initialization?
Zero initialization sets the object’s initial value to zero (or null pointer / false as appropriate). Static storage duration objects get it automatically before dynamic initialization. For automatic locals, use T{} or value initialization—do not wait for zero init. 아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
int global; // 0 (static duration → zero-initialized)
static int s; // 0 (static → zero-initialized)
void func() {
static int x; // 0 (static → zero-initialized)
int y; // ❌ indeterminate (automatic → NOT zero-initialized)
int z{}; // ✅ 0 (value-initialized)
}
Zero initialization results by type
| Type | Zero-init result | Example |
|---|---|---|
| Integer types | 0 | int x; → 0 (if static) |
| Floating-point | +0.0 | double d; → 0.0 (if static) |
bool | false | bool b; → false (if static) |
| Pointers | null pointer value | int* p; → nullptr (if static) |
| Arrays | Each element zero-initialized | int arr[5]; → {0,0,0,0,0} (if static) |
| Class types | Recursively zero-init members | Then constructors run |
Who gets zero initialization automatically?
Static storage duration
아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// Namespace scope
int globalVar; // Zero-initialized before main()
// Static local
void func() {
static int counter; // Zero-initialized on first call
}
// Static member
class MyClass {
static int count; // Zero-initialized before main()
};
int MyClass::count;
Thread-local storage
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
thread_local int threadVar; // Zero-initialized per thread
void func() {
thread_local int localThreadVar; // Zero-initialized per thread
}
Initialization phases for static objects
Static initialization happens in stages:
- Zero initialization — All bits set to zero
- Constant initialization —
constexpr/ compile-time constants - Dynamic initialization — Runtime constructors before
main()아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
int g1; // 1. Zero-init → 0
constexpr int g2 = 50; // 2. Constant-init → 50
int g3 = compute(); // 3. Dynamic-init (runtime)
int compute() {
return 42;
}
Locals vs static: Critical difference
아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
int g; // Static duration → zero-initialized
void test() {
static int s; // Static duration → zero-initialized
int a; // Automatic → NOT zero-initialized (indeterminate!)
int b{}; // Automatic → value-initialized (zero)
std::cout << "g = " << g << "\n"; // 0
std::cout << "s = " << s << "\n"; // 0
// std::cout << "a = " << a << "\n"; // ❌ UB: reading indeterminate value
std::cout << "b = " << b << "\n"; // 0
}
Common mistake: Assuming locals are “almost zero” like globals—they are not!
Real-world examples
1. Global counters
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// Automatically zero-initialized
int requestCount;
int errorCount;
void handleRequest() {
++requestCount;
if (error) {
++errorCount;
}
}
// Safe to use without explicit initialization
2. Static lookup tables
아래 코드는 cpp를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// Zero-initialized before main()
int frequencyTable[256];
void countCharacters(const std::string& text) {
for (char c : text) {
++frequencyTable[static_cast<unsigned char>(c)];
}
}
3. Singleton pattern
아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
class Logger {
static Logger* instance;
public:
static Logger& getInstance() {
if (!instance) { // instance is nullptr (zero-initialized)
instance = new Logger();
}
return *instance;
}
};
Logger* Logger::instance; // Zero-initialized to nullptr
Classes and zero initialization
Trivial types
아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
struct Point {
int x;
int y;
};
Point globalPoint; // Zero-initialized: {0, 0}
void func() {
Point localPoint; // ❌ NOT zero-initialized (indeterminate)
Point valuePoint{}; // ✅ Zero-initialized: {0, 0}
}
Non-trivial types
아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
class Widget {
int value_;
public:
Widget() : value_(42) {} // Constructor runs after zero-init
};
Widget globalWidget; // 1. Zero-init, 2. Constructor → value_ = 42
void func() {
static Widget staticWidget; // 1. Zero-init, 2. Constructor
Widget localWidget; // Just constructor (no zero-init first)
}
Common mistakes
Mistake 1: Expecting locals to be zero
다음은 cpp를 활용한 상세한 구현 코드입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
void badFunction() {
int sum; // ❌ NOT zero! Indeterminate value
for (int i = 0; i < 10; ++i) {
sum += i; // ❌ UB: using indeterminate value
}
}
// ✅ Fix
void goodFunction() {
int sum = 0; // Explicit initialization
for (int i = 0; i < 10; ++i) {
sum += i;
}
}
Mistake 2: Relying on zero for non-trivial types
아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
struct Data {
std::string name; // Non-trivial
int count;
};
Data globalData; // Zero-init doesn't make name = "" directly
// name's constructor runs after zero-init
void func() {
Data localData; // ❌ count is indeterminate!
Data valueData{}; // ✅ Both members properly initialized
}
Mistake 3: Using memset on non-trivial types
아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
struct Widget {
std::string name;
int value;
};
Widget w;
// ❌ WRONG: Destroys std::string's internal state
memset(&w, 0, sizeof(w));
// ✅ Correct: Use value initialization or assignment
Widget w{}; // or
w = Widget{};
Zero initialization vs value initialization
| Initialization | Syntax | Static objects | Local objects |
|---|---|---|---|
| Zero | int x; (static) | ✅ Zero | ❌ Indeterminate |
| Value | int x{}; | ✅ Zero | ✅ Zero |
| Default | int x; (local) | ✅ Zero first | ❌ Indeterminate |
| 아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요. |
// Static storage
int g1; // Zero-init → 0
int g2{}; // Value-init (includes zero) → 0
void func() {
// Automatic storage
int a; // Default-init → indeterminate ❌
int b{}; // Value-init → 0 ✅
}
BSS segment
BSS (Block Started by Symbol): Uninitialized data segment where zero-initialized globals live. 아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
int globalArray[1000000]; // 4MB in BSS (not in executable file)
int main() {
// globalArray is zero-initialized at program start
// No 4MB added to executable size!
}
Benefit: Large zero-initialized arrays don’t bloat executable size.
Static initialization order fiasco
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// file1.cpp
int computeValue() { return 42; }
int value1 = computeValue(); // Dynamic init
// file2.cpp
extern int value1;
int value2 = value1 * 2; // ⚠️ Order undefined across TUs!
// If value2 initializes first, value1 is still zero!
Solution: Use function-local statics or constexpr:
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// file1.cpp
constexpr int value1 = 42; // Constant init (safe)
// Or
int& getValue1() {
static int value = 42; // Initialized on first call
return value;
}
Performance implications
Zero cost: Zero initialization of static objects happens before main() and is typically free (BSS segment).
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// No runtime cost
int largeArray[1000000]; // BSS segment, zero at load time
// Runtime cost
void func() {
int largeArray[1000000]{}; // Stack allocation + zero-fill
}
Debugging zero initialization
Check if variable is zero-initialized
아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
#include <type_traits>
template<typename T>
void checkInit() {
if constexpr (std::is_trivially_default_constructible_v<T>) {
std::cout << "Trivial: static objects zero-initialized\n";
} else {
std::cout << "Non-trivial: constructor runs\n";
}
}
checkInit<int>(); // Trivial
checkInit<std::string>(); // Non-trivial
Compiler support
| Compiler | Zero initialization | BSS optimization |
|---|---|---|
| GCC | All versions | Yes |
| Clang | All versions | Yes |
| MSVC | All versions | Yes |
Related posts
- C++ Value initialization
- C++ Default initialization
- C++ Constant initialization
- C++ Initialization order
- C++ Static initialization order fiasco
Keywords
C++, zero initialization, static initialization, BSS, globals, static storage, initialization, memory