728x90

Member Initializer List (멤버 초기화 리스트)를 알아보기 전 먼저 Class의 Constructor (생성자), Destructor (소멸자)에 대해서 얘기해보자. 

 

Class Dog
{
public:
    Dog()
    {
    	//std::cout << "Constructor" << std::endl;
    }
    ~Dog()
    {
    	//std::cout << "Destructor" << std::endl;
    }
private:    
};

Dog라는 Class를 생성했다. 위와 같이 클래스의 이름과 멤버 함수의 이름이 동일한 것을 볼 수 있다. Constructor는 클래스의 이름을 함수 이름으로 정의해주면 되고 Destructor의 경우 '~'를 붙여 정의해주면 된다. 

 

 

Member Initializer List

먼저 멤버 초기화 리스트를 이용하지 않고 클래스를 구성해보면 아래와 같다. 

Class Dog
{
public:
    Dog(int age)
    {
    	mAge = age;
    }
    ~Dog()
    {
    	//std::cout << "Destructor" << std::endl;
    }
private:
	int mAge;
};

필자도 원래 항상 이런 식으로 코드를 짜 왔다. 멤버 초기화 리스트는 기존 함수명 괄호 뒤에 세미콜론 :으로 표기한다. 그다음 초기화하고자 하는 변수들을 쉼표로 구분하고 괄호를 이용하여 초기화를 진행한다. 

Class Dog
{
public:
    Dog(int age) : mAge(age) {};
    ~Dog()
    {
    	//std::cout << "Destructor" << std::endl;
    }
private:
	int mAge;
};

멤버 초기화 리스트를 하면 코드가 간략해지는 것 의외의 차이점을 못 찾을 수 있지만 아래의 예시를 보면 왜 멤버 초기화 리스트를 사용하는지 알 수 있다. 


#include <iostream>

class Dog
{
public:
    Dog() : mAge{ 1 } {};
    Dog(int age) : mAge{ age } {};
	
private:
    int mAge;
};

class Zoo
{
public:
     //Zoo(int dogAge) : mong(Dog(dogAge)) {};
    Zoo(int dogAge)
    {
        mong = Dog(dogAge);
    }
private:
    Dog mong;
};

int main()
{
    Zoo cppZoo(5);

    return 0;
}

Zoo라는 클래스를 추가로 생성하여 Zoo클래스에 Dog객체가 생성되도록 만들었다. Zoo의 생성자를 보게 되면 주석 처리된 코드는 Member Initializer List를 이용하여 객체의 생성자를 호출하고 주석이 아닌 Zoo생성자는 일반적으로 대입 연산자를 통해 Zoo클래스의 mong객체를 초기화한다. 

 

위 코드를 어셈블리어로 확인을 하게 되면 둘의 차이를 명백하게 확인할 수 있다. 

*참고로 필자는 아직 어셈블리어를 이해하지 못하고 어셈블리 코드를 확인하기 위해 Compiler explorer를 이용했다. 

 

대입 연산자를 통해 mong객체를 초기화하는 코드를 어셈블리어 변환한 모습이다. 우측 어셈블리 코드를 확인해 보면 Zoo::Zoo(int)에 생성자 코드를 보게 되면 먼저 Dog::Dog()인 기본 Dog생성자가 1번 호출이 되고 Dog::Dog(int) 생성자가 한번 더 호출이 되게 된다. 이 뜻은 먼저 임시 객체가 생성이 되고 그 객체에 dogAge의 값으로 초기화가 되 후에 mong객체에 대입 (mov키워드) 이 되는 방식이다. 하지만 대입 초기화 연산자를 이용할 경우는 아래와 같다. 

똑같이 우측 어셈블리 코드를 보면 Zoo::Zoo(int)에서 Dog::Dog(int) 생성자가 한번 호출이 되고 그다음 mov키워드가 없는 것을 확인할 수 있다. 이러한 이유 때문에 메모리 관점에서 효율적인 코드를 짜기 위해서 Member initializer list를 사용하는 것이다. 

+ Recent posts