초기화 리스트

falseman_go·2022년 5월 6일
0

R&D-Language

목록 보기
8/24

초기화 리스트

코드를 작성하다보면 변수를 사용할 때 초기화하거나 안하는 경우가 있다. 가급적 초기화를 하고 변수를 사용하는 것이 바람직한데 초기화를 하는 이유는 대표적으로 버그를 예방하기 위함에 있다. 특히 객체를 사용할 때 멤버 변수를 초기화하지 않으면 컴파일러가 에러가 발생했다고 할 정도로 초기화는 중요하다. 객체에서 멤버 변수를 초기화하는 방법에는 3가지 방법이 있다.

생성자 내에서 초기화

class Person {
public:
	int _id;
	int _hp;

	Person() {
		_hp = 100;
		_id = 1;
	}

	Person(int id) {
		_hp = 100;
		_id = id;
	}
};

위의 코드는 사람을 추상화하여 클래스로 만들고 생성자를 활용하여 초기화하는 코드이다. 처음 프로그래밍을 배운다면 가장 먼저 접하는 방법이라고 생각한다.

C++ 11 문법

C#을 먼저 배웠다면 이 방법은 가장 친숙해보일 것이라 생각한다. 아래의 코드는 인벤토리를 간단하게 추상화하여 생성자와 소멸자를 간단히 작성한 코드이다.

class Inventory {
public:
	int _size = 10;

	Inventory() { std::cout << "Inventory() 생성자 호출" << std::endl; }
	Inventory(int size) { 
		std::cout << "Inventory(int size) 생성자 호출" << std::endl;
		_size = size;
	}

	~Inventory() { std::cout << "~Inventory() 소멸자 호출" << std::endl; }
};

멤버 변수의 선언과 동시에 초기화하는 방법인데, 나도 C#을 자주 쓰다보니 저 방법을 많이 사용했었다.

초기화 리스트

마지막으로 초기화 리스트를 사용하여 초기화 하는 방법이다.

class Wanda : public Person {
public :
	int _stamina;
	Inventory _inventory;

	Wanda() :Person(3),_stamina(200) {
		_inventory = Inventory(20);
	}
};

Person 클래스를 상속한 Wanda 클래스는 멤버 변수로 기력과 인벤토리를 가지고 있는데, 인벤토리는 앞서 작성했던 클래스 타입의 멤버 변수이다. 지난번에 정리했던 내용중에 생성자를 호출할 때 원하는 부모 생성자를 골라 호출하는 방법에 대해 정리했었는데 그것을 초기화 리스트라고 부르는 것을 알게 되었다. 부모 생성자를 호출하는 것 뿐만 아니라 가지고 있는 멤버 변수를 초기화할 수도 있다. 콤마를 찍고 멤버 변수에 소괄호를 사용하여 값을 넣으면 된다. 그런데 여기서 코드를 살펴보면 클래스 타입의 인벤토리 멤버 변수만 생성자 내에서 초기화가 되고 있는 것을 확인할 수 있는데, 앞서 인벤토리의 생성자와 소멸자에 호출된다는 텍스트를 출력하게 하였다. 메인 함수의 첫 부분에 중단점을 걸고 호출 되는 순서를 살펴보면 불필요하게도 인벤토리의 생성자와 호출자가 2번이나 호출되고 있는 점을 확인할 수 있다.

이렇게 실행이 된 이유는 처음 멤버 변수에 기본 생성자가 호출이 되고, 그곳에 크기를 지정하는 생성자를 호출하여 할당하였다. 그랬기 때문에 처음에 기본 생성자로 호출한 인벤토리가 사용할 일이 없어 소멸자가 호출되어 소멸해버렸고, 그대로 메인 함수를 실행하는 코드를 마지막으로 크기를 지정한 인벤토리 객체가 소멸자를 호출해버린 것이다. 이처럼 두번씩이나 생성자와 소멸자가 호출되어지는 것을 막기 위해 클래스 타입의 멤버 변수는 초기화 리스트를 사용하여 초기화해주는 것이 좋다. 앞의 코드를 살짝 고치면 아래와 같다.

class Wanda : public Person {
public :
	int _stamina;
	Inventory _inventory;

	Wanda() :Person(3),_stamina(200),_inventory(20) {}
};

profile
정리하는 블로그

0개의 댓글