[ C++ : 초기화 리스트 ]
멤버 변수를 초기화하는 다양한 문법
초기화는 왜 해야할까 ?
클래스에서 멤버변수를 초기화 해주지 않는다면 쓰레기 값이 들어있음.
visual studio C++ x86 Debug를 기준으로 보자.
class Knight내에서 int hp가 있고, 기본 생성자로만 생성한다면
hp에는 0xcccccccc라는 값이 들어있다.
→ 이 값은 초기화 되지 않은 쓰레기 값
방금 만든 Knight의 hp가 의도치 않게 쓰레기값인 음수로 설정되어
곧 바로 죽을 수 있다.
처음에 설계를 할 때는 들어가자마자 정리정돈을 하고 시작해야지 예측할 수 없는 문제를 예방할 수 있다.
[ 초기화 방법 ]
- 생성자내에서
- 초기화리스트
- C++11 문법 (선언과 동시에 초기화)
[ 초기화 리스트 ]
- 상속 관계에서 원하는 부모 생성자를 호출할 때 필요하다.
- 생성자내에서 초기화 vs 초기화 리스트
-- 일반 변수는 별 차이 없음
-- 멤버 타입이 "클래스"인 경우 차이난다.
-- 정의함과 동시에 초기화가 필요한 경우 (ex 참조 타입, const 타입)
[ 여기서 잠깐 ]
클래스 설계를 할 때, 예를 들어 Inventory 클래스를 생각해보자
Knight가 Inventory를 가진다고 할 때, 다음 관계를 생각해 봐야 함
[ Is-A (Knight Is-A Player?) OK → 상속관계 ]
[ Has-A (Knight Has-A Inventory?) OK → 포함관계 ]
상속관계라면 "상속", 포함관계라면 "멤버 변수"가 된다.
그럼 Inventory 클래스를 멤버 변수로 갖게 되는데,
Knight의 생성자 선처리 영역에서 Inventory의 생성자도 호출된다.
Inventory 클래스의 생명 주기는 Knight를 따라서 생성되고 소멸된다.
갑자기 이 이야기는 왜 하는걸까?
생성자의 선처리 영역에서 부모의 다른 버전 생성자를 지정할 수 있었던 것 처럼
포함 관계가 있을 때도 Inventory를 내부에서 새로 만들어주는게 아니라 한 방에 처리할 수 있게 유도 해야 함.
→ 기존 생성자내에서 하나를 새로 생성하면, 선처리 영역에서 미리 Inventory를 생성하기 때문에 덮어써서 한번 더 생성하게 되고, 덮어쓴 후 기존에 생성된 부분은 필요없다고 느낄테니 "생성한 뒤에" 기존에 기본 생성자로 생성된 Inventory의 소멸자도 호출된다.
Knight() : Player(1), _hp(100), Inventory(50)
{
//
}
[ 결국 결론은 ? ]
초기화를 할 때는 일반적인 함수처럼 내부에서 하기보다는, "초기화 리스트"를 이용하는게 훨씬 더 좋다.
성능적인 이슈도 있지만 사실은 이렇게 할수밖에 없는 경우도 종종 생기게 되는데, 위에서 살펴 본 초기화 방법들 중 세 번째 경우인 "참조 타입, Const 타입"의 경우가 해당된다.
'컴퓨터공학 > C++' 카테고리의 다른 글
[Modern C++] std::forward (0) | 2024.09.14 |
---|---|
[Modern C++] Lambda (0) | 2024.09.11 |
[C++] 동적할당 (0) | 2024.08.23 |
[C++] 상속성 (0) | 2024.08.21 |
[C++] 생성자와 소멸자 (0) | 2024.08.20 |