[2026] C++ Zero Initialization | The All Bits Zero First Step

[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

TypeZero-init resultExample
Integer types0int x; → 0 (if static)
Floating-point+0.0double d; → 0.0 (if static)
boolfalsebool b; → false (if static)
Pointersnull pointer valueint* p; → nullptr (if static)
ArraysEach element zero-initializedint arr[5]; → {0,0,0,0,0} (if static)
Class typesRecursively zero-init membersThen 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:

  1. Zero initialization — All bits set to zero
  2. Constant initializationconstexpr / compile-time constants
  3. 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

InitializationSyntaxStatic objectsLocal objects
Zeroint x; (static)✅ Zero❌ Indeterminate
Valueint x{};✅ Zero✅ Zero
Defaultint 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

CompilerZero initializationBSS optimization
GCCAll versionsYes
ClangAll versionsYes
MSVCAll versionsYes

Keywords

C++, zero initialization, static initialization, BSS, globals, static storage, initialization, memory

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3