인프런 커뮤니티 질문&답변

starkshn님의 프로필 이미지
starkshn

작성한 질문수

[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문

연산자 오버로딩 #1

생성자 질문(타입 변환 생성자)

작성

·

249

0

opertor를 공부하면서 생성자 부분이 궁금해서 테스트를 해보았는데

class Player
{
public :
    int m_iHp;
    int m_iAttack;
    int m_iDefense;

public:
    Player()
        :
        m_iHp(100),
        m_iAttack(20),
        m_iDefense(5)
    {
        cout << "Player 기본 생성자!" << endl;
    }

    Player(int id)
        :
        m_iHp(200),
        m_iAttack(40),
        m_iDefense(10)
    {
        cout << "Player ID 받는 버젼 생성자!" << endl;
    }
    ~Player()
    {
        cout << "Player 소멸자!" << endl;
    }
};


class Knight : public Player
{
public:
    int m_iStat;

public:
    Knight()
        :
        m_iStat(10)
    {
        cout << "Knight 기본 생성자!" << endl;
    }
    Knight(int id)
        :
        Player(id),
        m_iStat(20)
    {
        cout << "Knight id 받는 버젼 생성자!" << endl;
    }
    ~Knight()
    {
        cout << "Knight 소멸자!" << endl;
    }

};


int main()
{
    Knight k1;
    k1 = 3;


    return 0;
}

현재 Knight k1을 만들게 되면은

콘솔창에 출력문이 이렇게 찍혀 햇갈리는 부분이 있어서 질문드립니다.

 

메모리를 확인해보니

k1의 주소(0x000000718D0FF688)는 이런값으로 안에 데이터들이 스택에 자리를 차지하게되어있었습니다.

이후 k1 = 3; 를 하게되면

Knight k1의 스택에 있는 주소가 가르키는 값들이 변경이 되는데 이는,

타입 변환 생성자(기타 생성자)를 통해 만들어진 객체를

만들어서 

"암시적 형변환"으로 만들어진 객체를 대입연산자로 k1의 주소에

멤버 변수 하나하나를 다 덮어 쓴 형태인거같더라구요

 

즉,  정리하자면

1) Knight k1; 을 하는 순간은 스택에 기본 생성자를 호출 한 상태로 올라간다.

 

2) k1 = 3 하였을 경우, 컴파일러가 암시적 형변환으로

인자를 하나를 받는 Knight의 타입 변환 생성자(기타 생성자)를 호출한뒤

k1의 주소에 '=' 연산자를 통해 멤버 변수 하나하나를 덮어쓴다. (얕은 복사)

 

여기서 궁금한점이

소멸자를 출력하는 문장이 두줄에 걸쳐서 나오는게 아니라

이런식으로 4줄에 걸쳐서 나오는데

이게 분명히 암시적 형변환으로 생성한 객체를 생성하고 

기본생성자로 만든 k1에 멤버 변수들을 덮어썻다고 생각해서 

스택에는 Knight의 객체가 하나밖에 없는 상태로 봤는데

 

콘솔창을 확인하면 k1뿐만 아니라 

k1 = 3을 하였을 때의 3에 해당하는 객체도 어딘가에 존재를 하는거 같은데

3이라는 정수를 컴파일러가 타입변환 생성자로 받아들여서 

인자를 하나만 받는 Knight객체를 만들어서 '=' 연산자를 통해 k1에다가 멤버 변수를 다 덮어 씌우는데

정수 3을통해서 만들어진 객체도 스택에 올라간 다음에

값만 k1이라는 객체에 덮어 씌우는건가요..??

 

맞는말인가요..???

답변 3

0

3이라는 정수를 컴파일러가 타입변환 생성자로 받아들여서 

인자를 하나만 받는 Knight객체를 만들어서 '=' 연산자를 통해 k1에다가 멤버 변수를 다 덮어 씌우는데

정수 3을통해서 만들어진 객체도 스택에 올라간 다음에

값만 k1이라는 객체에 덮어 씌우는건가요

-> 제가 알아본 바로는 이게 맞습니다. 그리고 타입변환 생성자로 만들어진 임시 객체는 k1=3; 대입 직후에 쓸모가 없어지므로 임시 객체에 대한 소멸자가 호출됩니다.
그리고 k1을 생성한 이후의 k1=3; 대입은 대입 연산자입니다.

0

starkshn님의 프로필 이미지
starkshn
질문자

Knight k1 = 3; 같은경우는

타입 변환생성자(인자를 하나받는 생성자) 호출하여 객체를 만드는 것이고(생성자 한번만 호출)

 

Knight k1;

k1 = 3 일경우에는

 

먼저 "기본생성자" 호출하여 객체(k1) 만든뒤,

 

인자를 하나만 받는 생성자(타입 변환생성자 ) 호출하여 객체(3) 만든뒤(임시객체 생성)

 

(암시적 형변환을 제한하고싶다면 인자를 하나만 받는 생성자 앞에 explicit 키워드 붙이기)

 

기본생성자를 호출하여 만들어진 k1

 

= 3; 이것이

 

k1 복사 대입 연산자" 수행한것인가요?

 

0

Rookiss님의 프로필 이미지
Rookiss
지식공유자

C++이 정말 문법이 지저분한게
Knight k1 = 3; 을 할 때와

Knight k1;
k1 = 3;을 할 때의 의미가 완전히 다릅니다.

전자라면 k1에 int 생성자를 호출하겠지만,
후자는 임시 객체를 만든 다음 복사가 일어나기 때문에
임시 객체의 소멸자, 그리고 k1의 소멸자가 두 번 호출된 것이죠.



starkshn님의 프로필 이미지
starkshn

작성한 질문수

질문하기