Dominic Hamon (dominic@google.com) 작성
최초 게시일: 2018년 4월 19일
최종 업데이트: 2020년 4월 6일

빠른 링크: abseil.io/tips/146


“성공으로 가는 길은 항상 공사 중이다.”
– 릴리 톰린


요약

안전성과 가독성을 위해, 스칼라(scalar) 객체는 명시적으로 값을 설정할 때까지 적절한 값으로 초기화되지 않는다고 가정하세요. 초기화를 사용하면 스칼라 값을 안전한 값으로 설정할 수 있습니다.


소개

객체가 생성될 때, 초기화될 수도 있고 초기화되지 않을 수도 있습니다. 초기화되지 않은 객체를 읽는 것은 안전하지 않으며, 객체가 초기화되지 않았는지 이해하는 것은 쉽지 않습니다.

초기화 여부를 이해하려면 먼저 생성 중인 타입이 스칼라(scalar), 집계(aggregate), 혹은 다른 타입인지 알아야 합니다.

또한, 객체가 안전하게 읽을 수 있는 값으로 초기화되었는지 여부는 명시적인 **초기화자(initializer)**를 사용했는지에 따라 달라집니다. 초기화자는 (), {}, 또는 = {} 형태로 객체 이름 뒤에 나옵니다.

이 규칙은 직관적이지 않으므로, 객체가 초기화되었는지 보장하려면 초기화자를 제공하는 것이 가장 쉬운 방법입니다. 이를 **값 초기화(value-initialization)**라고 하며, 컴파일러가 스칼라 및 집계 타입에 대해 수행하는 **기본 초기화(default-initialization)**와는 다릅니다.


사용자 정의 생성자

사용자 정의 생성자가 정의된 타입은 집계 타입이 아니며, 값 초기화와 기본 초기화가 모두 생성자를 호출하므로 초기화가 더 간단합니다:

CPP
struct Foo {
  Foo() : v() {}

  int v;
  std::string s;
};

int main() {
  Foo default_foo;
  Foo value_foo = {};
}
클릭하여 더 보기

위 코드에서 = {}value_foo의 값 초기화를 트리거하며, 이는 Foo의 기본 생성자를 호출합니다. 생성자 초기화 리스트가 v를 값 초기화하므로, v는 안전하게 읽을 수 있습니다. v는 클래스 타입이 아니므로 이는 **제로 초기화(zero-initialization)**라는 값 초기화의 특별한 경우로, value_foo.v0이 됩니다.


사용자 선언 생성자와 사용자 정의 생성자

다음 코드처럼 생성자를 = default로 선언할 수 있습니다:

CPP
struct Foo {
  Foo() = default;

  int v;
};

int main() {
  Foo default_foo;
  Foo value_foo = {};
}
클릭하여 더 보기

이 경우, Foo사용자 선언(user-declared) 생성자를 가지지만, 사용자 정의(user-provided) 생성자는 아닙니다. 따라서 default_foo.v는 초기화되지 않고, value_foo.v제로 초기화됩니다.


명시적 값 초기화

값을 명시적으로 초기화하는 것이 독자를 위해 더 좋은 선택입니다. 예:

CPP
struct Foo {
  Foo() : v(0) {}

  int v;
};
클릭하여 더 보기

기본 멤버 초기화

멤버 변수를 선언 시 초기화하면, 기본 초기화와 값 초기화의 혼란을 방지할 수 있습니다:

CPP
struct Foo {
  int v = 0;
};
클릭하여 더 보기

프로 팁: 스칼라 제로 초기화

스칼라 값이 안전하게 초기화되는 조건:


권장 사항


추가 자료


라이선스

저작자: Jaehun Ryu

링크: https://jaehun.me/posts/abseil-tip-146-%EA%B8%B0%EB%B3%B8-%EC%B4%88%EA%B8%B0%ED%99%94%EC%99%80-%EA%B0%92-%EC%B4%88%EA%B8%B0%ED%99%94/

라이선스: CC BY 4.0

이 저작물은 크리에이티브 커먼즈 저작자표시 4.0 국제 라이선스에 따라 이용할 수 있습니다. 출처를 밝히면 상업적 목적을 포함해 자유롭게 이용 가능합니다.

댓글

검색 시작

검색어를 입력하세요

↑↓
ESC
⌘K 단축키