zero_initialization — 0 초기화

zero_initialization — 0 초기화 (Zero-initialization)

**0 초기화(zero-initialization)**는 객체의 초기 값을 0으로 설정하는 초기화예요. 언어에 전용 문법은 없고, 정적/스레드 로컬 변수나 값 초기화의 일부로 수행돼요.

static int n; 같은 전역 변수는 자동으로 0 초기화되어 0 값을 가져요. 포인터라면 널 포인터 값으로 초기화돼요.

출처: cppreference

본문

0 초기화는 객체의 초기 값을 0으로 설정해요.

문법 (Syntax)

참고: 이것은 0 초기화의 문법이 아니에요. 0 초기화에는 언어에 전용 문법이 없어요. 아래는 0 초기화를 수행할 수 있는 다른 종류의 초기화 예시예요.

static T object ;
T () ;
T t = {} ;
T {} ;
CharT array[n] = " short-sequence ";

설명 (Explanation)

0 초기화는 다음 상황에서 수행돼요.

  1. 상수 초기화를 받지 않는 정적 또는 스레드 로컬 저장 기간의 모든 이름 있는 변수에 대해, 다른 초기화 전에
  2. 비클래스 타입과 생성자가 없는 값 초기화된 클래스 타입 멤버의 값 초기화 시퀀스의 일부로 (초기화자를 제공받지 않은 애그리거트 요소의 값 초기화 포함)
  3. 어떤 문자 타입의 배열이 너무 짧은 문자열 리터럴로 초기화될 때, 배열의 나머지 부분이 0 초기화될 때

0 초기화의 효과

  • T가 스칼라 타입이면, 정수 리터럴 0(영)을 명시적으로 T로 변환해 얻은 값으로 객체가 초기화돼요.
  • T가 비유니온 클래스 타입이면:
    • 모든 패딩 비트가 0 비트로 초기화
    • 각 비정적 데이터 멤버가 0 초기화
    • 각 비가상 기반 클래스 부분 객체가 0 초기화
    • 객체가 기반 클래스 부분 객체가 아니면 각 가상 기반 클래스 부분 객체가 0 초기화
  • T가 유니언 타입이면:
    • 모든 패딩 비트가 0 비트로 초기화
    • 객체의 첫 번째 비정적 이름 있는 데이터 멤버가 0 초기화
  • T가 배열 타입이면 각 요소가 0 초기화
  • T가 참조 타입이면 아무것도 하지 않음

노트 (Notes)

비로컬 초기화에서 설명했듯, 상수 초기화되지 않는 정적·스레드 로컬 변수는 다른 초기화가 일어나기 전에 0 초기화돼요. 비클래스 비로컬 변수의 정의에 초기화자가 없으면 기본 초기화는 아무것도 하지 않아, 앞선 0 초기화의 결과를 그대로 두어요.

0 초기화된 포인터는 그 타입의 널 포인터 값이에요. 널 포인터의 값이 정수 0이 아니어도 마찬가지예요.

예제 (Example)

#include <iostream>
#include <string>

struct A
{
    int a, b, c;
};

double f[3];   // 세 개의 0.0 으로 0 초기화

int* p;        // 널 포인터 값으로 0 초기화
               // (값이 정수 0 이 아니어도)

std::string s; // 불확정 값으로 0 초기화된 뒤,
               // std::string 기본 생성자로 "" 로 기본 초기화

int main(int argc, char*[])
{
    delete p; // 널 포인터 삭제는 안전

    static int n = argc; // 0 으로 0 초기화된 뒤 argc 로 복사 초기화
    std::cout << "n = " << n << '\n';

    A a = A(); // A a{}; 또는 A a = {}; 와 같은 효과
    std::cout << "a = {" << a.a << ' ' << a.b << ' ' << a.c << "}\n";
}

출력:

n = 1
a = {0 0 0}

static int n = argc;는 먼저 0 초기화되어 0이 된 뒤, 그 다음에 argc로 복사 초기화돼요. A a = A();A의 멤버들이 0 초기화되어 a = {0 0 0}이 돼요.

더 알아보기 (Learn more)

cppreference