🙇‍♀️타입 변환 (포인터)

🪐복습

// Stack [ type(4) dbid(4) dummy(4096) ]
Item item;

// Stack [ 주소(4~8) ] -> Heap [ type(4) dbid(4) dummy(4096) ]
Item* item2 = new Item();

포인터로 만들어준 것은 주소값만 있기 때문에 소멸자가 자동으로 만들어지지 않는다. delete를 해줘야 한다. 해주지 않으면 메모리 누수가 일어난다.

void TestItem(Item item)
{

}

void TestItemPtr(Item* item)
{

}

TestItem(item);
TestItem(*item2);

TestItemPtr(&item);
TestItemPtr(item2);

헷갈리지만 포인터를 매개변수로 받는 함수의 사용법 익혀두자.

TestItem의 경우 복사 되는 함수지만 새로운 객체를 만들어 내는 것은 같기 때문에 복사 생성자가 만들어진다. TestItemPtr은 원본을 그대로 쓰는거 이므로 복사 생성자가 없다.

// 배열
{
	cout << "------------------------------" << endl;

	// 진짜 아이템이 100개 있는 것 (스택 메모리에 올라와 있는)
	Item item3[100] = {  };

	cout << "------------------------------" << endl;

	// 아이템이 100개 있을까?
	// 아이템을 가리키는 바구니가 100개. 실제 아이템은 1개도 없을 수도 있음
	Item* item4[100] = {};

	for (int i = 0; i < 100; i++)
		item4[i] = new Item();

	cout << "------------------------------" << endl;
	
	for (int i = 0; i < 100; i++)
		delete item4[i];

	cout << "------------------------------" << endl;

}

item3는 실제로 아이템이 있지만 item4는 주소가 담긴 바구니만 100개다. item4에 아이템을 넣기 위해서 하나하나 동적할당을 이용해 넣어주고 delete도 해줘야 한다.

🙇‍♀️타입 변환 (포인터)

  • 명시적으로 변환 할 때는 항상 조심해야 한다
  • 암시적으로 변환이 가능하다면 안전하다?
  • 항상 암시적으로만 사용할 수 없다.

  • 상속 관계에 있을 때 최상위 부모의 소멸자는 virtual을 붙여야한다.
    • 원래는 자식의 타입마다 delete를 해야 하는데 virtual을 붙여서 가상함수로 만들면 delete부모;를 해도 자식까지 알아서 delete된다.

결론

  1. 포인터 vs 일반 타입 : 차이를 이해하자
  2. 포인터 사이의 타입 변환(캐스팅)을 할 때는 매우 매우 조심해야한다.
  3. 부모-자식 관계에서 부모 클래스의 소멸자에는 까먹지 말고 virtual을 붙이자!!!!

태그:

카테고리:

업데이트: