[Effective C++] 항목 4
항목 4 : 객체를 사용하기 전에 반드시 그 객체를 초기화하자
-
C++ 객체 초기화 규칙이 조금 복잡. 그러므로 모든 객체를 사용하기 전에 초기화.
- 대입과 초기화를 헷갈리지 말자.
- 어떤 객체든 그 객체의 데이터 멤버는 생성자 본문이 실행되기 전에 초기화 되어야 한다.
- 멤버 초기화 리스트를 사용하자.
- 대입 시 : 기본 생성자 호출 -> 복사 대입 연산자 호출
- 초기화 리스트 사용 시 : 복사 생성자 호출
- 클래스 멤버를 모두 초기화 리스트에 올리는 정책을 사용할 시 어떤 멤버가 초기화되지 않을 수 있다는 사실의 부담감이 없어진다.
-
상수나 참조자 데이터 멤버는 대입이 불가능하므로 반드시 초기화되어야 하므로 필수로 초기화 리스트에 넣어 주어야 한다.
- 객체를 구성하는 데이터의 초기화 순서(컴파일러 상관 없이 동일)
- 기본 클래스가 파생 클래스보다 먼저 초기화
- 클래스 데이터 멤버는 선언된 순서대로 초기화 -> 멤버 초기화 리스트 순서와는 상관 없이!(초기화 리스트와 선언 순서 맞춰주자.)
- 비지역 정적 객체의 초기화 순서는 개별 번역 단위에서 정해진다.
- 정적 객체 : 전역 객체, 네임 스페이스 유효범위에 정의된 객체, 클래스 내 static 객체, 함수 내 static 객체, 파일 유효범위에서 static 객체
- 함수 내 정적객체 : 지역 정적 객체(local static object)
- 나머지 정적 객체 : 비지역 정적 객체(non-local static object)
- 번역 단위 : 컴파일을 통해 하나의 목적 파일을 만드는 바탕이 되는 소스코드.(기계어가 된 소스 파일 + #include 하는 파일(들))
- 별개의 번역 단위에서 정의된 비지역 정적 객체들의 초기화 순서는 미정!
- 싱글톤 패턴으로 만들어서 해결 가능
- 함수 속으로 비지역 정적 객체를 옮겨 지역 정적 객체를 만든다. 지역 정적 객체는 함수 호출 중 그 객체 정의에 최초로 닿았을 때 초기화된다.
- 다중 쓰레드시 초기화 순서에 따른 미정의 문제를 방지하기 위해 참조자 반환 함수를 전부 손으로 불러주면 초기화와 관련된 경쟁상태가 없어진다.(다중 쓰레드 전 시동단계에서)
- 멤버가 아닌 기본 제공 타입은 경우에 따라 초기화가 되기도 하고 안되기도 해서 직접! 꼭! 초기화해 주어야 한다.