초기화 리스트

 

인프런 Rookiss님의 'Part1: C++ 프로그래밍 입문' 강의를 기반으로 정리한 필기입니다. 
😎[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 강의 들으러 가기!

 

 


 

초기화를 하는 이유는?


-  버그 예방에 중요하다.

-  포인터 등 주소값이 연루되어 있을 경우, 유의해야 한다.

 

#include <iostream>
using namespace std;

class Knight{

public:
    int _hp;  // 쓰레기 값
};

int main(){
    Knight k;

    cout << k._hp << endl;
}

빌드 통과 X

 

#include <iostream>
using namespace std;

class Knight{
public:
    Knight() {  }

public:
    int _hp;  // 쓰레기 값
};

int main(){
    Knight k;

    cout << k._hp << endl;
}

Knight() 생성자를 넣으면 빌드 통과 O

 

 

#include <iostream>
using namespace std;

class Knight{
public:
    Knight() {   }

public:
    int _hp;  // 쓰레기 값
};

int main(){
    Knight k;

    cout << k._hp << endl;

    if (k._hp < 0){
        cout << "Knight is Dead" << endl;
    }

    return 0;
}

_hp에 쓰레기값이 할당된다.

쓰레기값이 로직에 통과되어 의도치 않은 결과가 나올 수 있으니 조심해야 한다. 경우에 따라 나비효과로 나중에 큰 문제를 발생시킬 수 있다. 그래서 초기화가 필요하다.

 


 

초기화 방법

 

초기화 방법

-  생성자 내에서 초기화 

초기화 리스트

-  C++11 문법

 


초기화 리스트

-  일단 상속 관계에서 원하는 부모 생성자 호출할 때 필요하다

-  생성자 내에서 초기화 vs 초기화 리스트

  • 일반 변수는 별차이 없음
  • 멤버 타입이 클래스인 경우 차이가 난다
  • 정의함과 동시에 초기화가 필요한 경우 (참조 타입, const 타입)

 

#include <iostream>
using namespace std;

class Inventory
{
public:
    Inventory() { cout << "Inventory()" << endl; }
    Inventory(int size) { cout << "Inventory(int size)" << endl; _size = size; }

    ~Inventory() { cout << "~Inventory()" << endl; }

public:
    int _size = 10;
};

class Player
{
public:
    Player() {}
    Player(int id) {}
};

// Is-A (Knight Is-A Player? 기사는 플레이어다 ) OK -> 상속관계
// Is-A (Knight Is-A Inventory? 기사는 인벤토리냐? ) NO -> 상속관계X
// Has-A (Knight Has-A Inventory? 기사는 인벤토리를 포함하고 있다. 갖고 있다) OK -> 포함관계

class Knight : public Player
{
public:
    Knight() : Player(1), _hp(100) // 초기화 리스트 사용
        /*
        선처리 영역

        Inventory()    // _inventory = Inventory()로 해석해서 실행
        */
    {
        _hp = 100;        
    }

public:
    int _hp = 200;  // 쓰레기 값
    Inventory _inventory;
};

int main()
{
    Knight k;

    cout << k._hp << endl;

    if (k._hp < 0)
    {
        cout << "Knight is Dead" << endl;
    }

    return 0;
}

 

 

 


 

초기화 리스트 예제 

 

#include <iostream>
using namespace std;

class Inventory
{
public:
    Inventory() { cout << "Inventory()" << endl; }                               
    Inventory(int size) { cout << "Inventory(int size)" << endl; _size = size; } 

    ~Inventory() { cout << "~Inventory()" << endl; }                             

public:
    int _size = 10;
};

class Player
{
public:
    Player() {}
    Player(int id) {}
};

class Knight : public Player
{
public:
    Knight() : Player(1), _hp(100)
        /*
        선처리 영역

        Inventory()    // _inventory = Inventory()로 해석해서 실행

        */
    {
        _hp = 100;
        _inventory = Inventory(20);  // _inventory = Inventory() 오버라이딩 
    }

public:
    int _hp = 200;  // 쓰레기 값
    Inventory _inventory;
};

int main()
{
    Knight k;

    cout << k._hp << endl;

    if (k._hp < 0)
    {
        cout << "Knight is Dead" << endl;
    }

    return 0;
}

Knight() : Player(1), _hp(100)

선처리 영역에서 Inventory()를 호출하고 Inventory()를 생성하고 

그 후, 아래의 _inventory = Inventory(20)를 호출하여 Inventory(int size)를 생성하여 오버라이드한다.

 

그래서 소멸자 ~Inventory()를 2개 호출한다.


 

초기화 리스트 예제코드 - 정의함과 동시에 초기화가 필요한 경우 (참조 타입, const 타입)

 

#include <iostream>
using namespace std;

class Inventory
{
public:
    Inventory() { cout << "Inventory()" << endl; }                               
    Inventory(int size) { cout << "Inventory(int size)" << endl; _size = size; } 

    ~Inventory() { cout << "~Inventory()" << endl; }                             

public:
    int _size = 10;
};

class Player
{
public:
    Player() {}
    Player(int id) {}
};

class Knight : public Player
{
public:
    Knight() : Player(1), _hp(100), _inventory(20), _hpRef(_hp), _hpConst(100)  // 다음과 같이 초기화 리스트로 하는 방법 추천.
        /*
        선처리 영역

        */
    {
        _hp = 100;

        // _hpRef = _hp;      // 선처리 영역에 들어가지 못해 문제가 생긴다.
        // _hpConst = 100;    // 선처리 영역에 들어가지 못해 문제가 생긴다.
    }

public:
    int _hp = 200;  // 쓰레기 값
    Inventory _inventory;

    int& _hpRef;
    const int _hpConst;
};

int main()
{
    Knight k;

    cout << k._hp << endl;

    if (k._hp < 0)
    {
        cout << "Knight is Dead" << endl;
    }

    return 0;
}

Knight() : Player(1), _hp(100), _inventory(20)

_hpRef = _hp;      // 선처리 영역에 들어가지 못해 문제가 생긴다.
_hpConst = 100;    // 선처리 영역에 들어가지 못해 문제가 생긴다.

 

선처리 영역에서 초기화 리스트를 사용해야 한다. 

Knight() : Player(1), _hp(100), _inventory(20), _hpRef(_hp), _hpConst(100)