# 생성자 없는 초기화 필요성

> Clean Markdown view of GeekNews topic #15702. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=15702](https://news.hada.io/topic?id=15702)
- GeekNews Markdown: [https://news.hada.io/topic/15702.md](https://news.hada.io/topic/15702.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2024-07-06T09:42:56+09:00
- Updated: 2024-07-06T09:42:56+09:00
- Original source: [consteval.ca](https://consteval.ca/2024/07/03/initialization/)
- Points: 1
- Comments: 1

## Topic Body

##### 나는 생성자가 없고 초기화해야 함

- **서론**
  - C++를 처음 배울 때, 컴파일러가 기본 생성자를 제공하는 경우에 대해 배웠음.
  - 특정 상황에서 객체가 초기화되지 않을 수 있는 위험성에 대해 고민하게 됨.

- **기본 초기화와 값 초기화**
  - `T t;`는 기본 초기화를 수행함.
    - `T`가 클래스 타입이고 기본 생성자가 있으면 실행됨.
    - `T`가 배열 타입이면 각 요소를 기본 초기화함.
    - 그렇지 않으면 아무것도 하지 않음.
  - `T t{};`는 값 초기화를 수행함.
    - `T`가 클래스 타입이면 기본 생성자가 없거나 사용자 제공 또는 삭제된 기본 생성자가 있으면 기본 초기화함.
    - 그렇지 않으면 0으로 초기화한 후 기본 초기화함.
    - `T`가 배열 타입이면 각 요소를 값 초기화함.
    - 그렇지 않으면 0으로 초기화함.

- **기본 생성자**
  - 기본 생성자를 선언하지 않으면 컴파일러가 암시적으로 기본 생성자를 선언함.
  - 암시적으로 선언된 기본 생성자는 빈 본문과 빈 멤버 초기화 목록을 가짐.
  - 예시:
    ```cpp
    struct T {
      int x;
      T() = default;
    };
    T t{};
    std::cout << t.x << std::endl; // 출력 결과는 0
    ```

- **암시적으로 정의된 기본 생성자**
  - 기본 생성자가 암시적으로 선언되거나 명시적으로 기본값으로 선언되면 컴파일러가 암시적으로 정의된 기본 생성자를 제공함.
  - 예시:
    ```cpp
    struct T {
      T();
    };
    T::T() = default;
    T t{};
    std::cout << t.x << std::endl; // 출력 결과는 쓰레기 값
    ```

- **기본 생성자를 제공할 수 없는 경우**
  - `T`가 비정적 참조 멤버를 가지고 있는 경우
  - `T`가 기본 생성할 수 없거나 소멸할 수 없는 비정적 멤버 또는 비추상 기본 클래스를 가지고 있는 경우
  - `T`가 기본 멤버 초기화자가 없는 `const` 비정적 멤버를 가지고 있는 경우

- **올바른 초기화**
  - `T t{};`는 리스트 초기화를 수행함.
  - 리스트 초기화는 직접 리스트 초기화와 복사 리스트 초기화로 나뉨.
  - 예시:
    ```cpp
    struct S {
      int a;
      float b;
      char c;
    };
    S s{3, 4.0f, 'S'}; // 생성자 호출 없음
    ```

- **리스트 초기화와 집합 초기화**
  - 집합 초기화는 리스트 초기화의 특별한 형태로, 클래스 또는 배열의 각 요소를 초기화 목록의 각 요소로 복사 초기화함.
  - 예시:
    ```cpp
    struct A {
      const int x;
    };
    A a{}; // a.x는 0으로 초기화됨
    ```

- **괄호를 사용한 초기화**
  - 괄호를 사용한 초기화는 직접 비리스트 초기화를 수행함.
  - 예시:
    ```cpp
    struct T {
      const int& r;
    };
    T t(42); // t.r은 42를 가리키는 참조
    ```

- **요약**
  - 초기화 규칙은 복잡하지만, 직접 생성자를 작성하면 대부분의 문제를 피할 수 있음.
  - 컴파일러에게 맡기지 말고, 직접 생성자를 작성하는 것이 좋음.

##### GN⁺의 의견
- 이 글은 C++ 초기화 규칙의 복잡성을 잘 설명하고 있음.
- C++의 초기화 규칙을 이해하는 것은 중요한데, 이는 코드의 안정성과 성능에 큰 영향을 미침.
- 직접 생성자를 작성하는 것이 초기화 문제를 피하는 가장 좋은 방법임.
- 비슷한 기능을 가진 다른 언어로는 Rust가 있으며, Rust는 초기화 규칙이 더 명확함.
- 새로운 기술을 채택할 때는 초기화 규칙과 같은 세부 사항을 잘 이해하고 사용하는 것이 중요함.

## Comments



### Comment 27001

- Author: neo
- Created: 2024-07-06T09:42:56+09:00
- Points: 1

###### [Hacker News 의견](https://news.ycombinator.com/item?id=40880932) 
- `t`의 초기화 결과는 0이 될 것임
  - 이는 `t`가 값 초기화되고, `T`가 사용자 정의 기본 생성자가 없기 때문에 객체가 0으로 초기화된 후 기본 생성자가 호출되기 때문임

- 기본 생성자는 멤버를 기본 초기화하며, 값 초기화와는 다름

- GCC는 이에 동의하는 것 같음

- 작성자가 실제로 `x`를 값 초기화하고 있다는 것을 놓쳤음
  - 결과는 기대와 다르게 나옴

- 규칙의 세부 사항은 복잡하고 때로는 비합리적인 부분이 있음
  - 그러나 대부분의 경우 기대한 결과를 얻을 수 있음

- 기본 초기화를 명시적으로 만드는 것이 큰 개선점이 될 것임
  - 값 초기화가 일반적이기 때문에 기본 초기화를 원할 때 주석을 작성해야 함
  - "std::array<int, 100> = void;"와 같은 구문이 더 나을 것임

- 리스트 초기화와 집합 초기화 사이의 연결고리는 리스트 초기화가 집합에 대해 수행될 때 집합 초기화가 수행됨
  - 단, 리스트에 하나의 인수만 있는 경우 직접 초기화가 수행됨

- 한 요소의 경우는 두 개 이상의 요소와 다르게 작동함
  - 이는 매개변수 팩에서 구조체를 생성하는 것이 점점 더 간단해지는 언어에서 발생함

- 자신의 생성자를 작성할 수 있으며, 하나의 요소만 제공된 튜플이나 배열을 초기화할 수 있음
  - 그러나 특수한 경우 잘못된 생성자가 호출될 수 있음

- C++11 초기화 리스트가 처음 나왔을 때 이를 발견하고 미쳤다고 생각했음

- "I Have No Mouth, and I Must Scream" (1967) 언급

- `T::T() = default;` 구문 사용

- 출력 결과가 0이 될 것이라고 기대하지만 실제로는 쓰레기 값이 나올 것임
  - 일부 것들은 완벽할 수 없음

- 라이브러리 소비자가 라이브러리의 동작을 변경할 수 있게 함

- 더 많은 C++의 복잡함을 원한다면 C++ FQA를 추천함
  - 15년이 지났지만 C++는 오래된 기능이나 동작을 거의 제거하지 않기 때문에 여전히 유효함

- 블로그 테마가 DEC 시대의 컴퓨터에서 영감을 받았지만 깔끔하고 미니멀함
  - 신선함

- 이 내용을 읽으면 어지러움을 느끼게 됨
  - Java 생성자와 객체 초기화를 이해하려고 했던 기억이 남

- Go와 Rust는 특별한 생성자가 없어서 많은 부분이 단순해짐
  - 생성자를 사용하지 않게 된 후 생성자를 그리워한 경험이 있는지 궁금함

- 모든 암묵적인 동작을 보여주는 C++ 도구가 있는지 궁금함
  - 예를 들어 추가된 모든 생성자, 암묵적 복사 생성자 등

- 클래스에 대해 잘못된 정보를 제공함
  - 생성자를 선언한 경우 기본 생성자를 제공하지 않으며 기본 초기화는 컴파일러 진단과 함께 실패함

- "T t;"는 "아무것도 하지 않는다"는 주장은 잘못됨
  - 예시 코드에서 `T t;`는 실패함

- 블로그 헤더에 DEC 전면 패널이 있음
