22.08.11 12:01 작성
·
230
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
2022. 08. 14. 13:29
Knight k1 = 3; 같은경우는
타입 변환생성자(인자를 하나받는 생성자)를 호출하여 객체를 만드는 것이고(생성자 한번만 호출)
Knight k1;
k1 = 3 일경우에는
먼저 "기본생성자"를 호출하여 객체(k1)를 만든뒤,
인자를 하나만 받는 생성자(타입 변환생성자 )를 호출하여 객체(3)를 만든뒤(임시객체 생성)
(암시적 형변환을 제한하고싶다면 인자를 하나만 받는 생성자 앞에 explicit 키워드 붙이기)
기본생성자를 호출하여 만들어진 k1 에
= 3; 이것이
k1에 복사 대입 연산자"를 수행한것인가요?
0
2022. 08. 12. 18:12
C++이 정말 문법이 지저분한게
Knight k1 = 3; 을 할 때와
Knight k1;
k1 = 3;을 할 때의 의미가 완전히 다릅니다.
전자라면 k1에 int 생성자를 호출하겠지만,
후자는 임시 객체를 만든 다음 복사가 일어나기 때문에
임시 객체의 소멸자, 그리고 k1의 소멸자가 두 번 호출된 것이죠.