• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    미해결

delete관련 질문

21.07.28 22:19 작성 조회수 102

1

class Base

{

public:

virtual ~Base() { cout << "Base소멸자" << endl; }

};

class Derived : public Base

{

public:

int* m_arr;

public:

Derived(const int& length) { m_arr = new int[length]; }

virtual ~Derived()

{

cout << "Derived 소멸자" << endl;

delete[] m_arr;

}

};

int main()

{

Derived * derived_ptr =new Derived(5);

Base* base_ptr = derived_ptr;

delete base_ptr;

return 0;

}

위 코드를 복붙하시면 보기 좀더 편할거라 생각됩니다.

 delete 함수는 메모리를 반환하고, 소멸자를 호출 해주는것으로 알고 있습니다.

또한, 자식클래스의 소멸자를 호출하면, 부모 클래스의 소멸자는 자동으로 호출되는 것으로 알고 있습니다.

또한 다형

 delete 함수 관점에서 생각해보면, 어떤포인터가

들어올것인데 이 포인터의 데이터 타입만큼 해당되는

메모리크기를 반환해줄것으로 생각됩니다.

delete base;에서 base의 데이터타입은 Base*입니다

그러면 부모클래스만큼의 크기만 반환하는것 아닙니까?

(부모클래스부분만 반환되고 자식클래스부분은 메모리에 남아있음)

delete가 프로그래머의 의도를 어떻게 알고

부모클래스, 자식클래스 합친만큼의 메모리를 반납하는건지 궁금합니다.

delete 내부적으로

포인터가 들어왔을때,

데이터타입과, 실제 내용물의 데이터타입을 비교해서

알아서 처리해주는것으로밖에 생각할수없는데....

정확히 알고 싶습니다.

답변 1

답변을 작성해보세요.

6

안소님의 프로필

안소

2021.07.29

"이 포인터의 데이터 타입만큼 해당되는 메모리크기를 반환해줄것으로 생각됩니다"

라고 말씀하셨는데 그렇지는 않습니다! 포인터의 타입이 Base 라고 해서 Base 객체 크기 만큼의 메모리만 해제되는 것이 아닙니다.

"delete 포인터" 라는 문법은 그 포인터 '값', 즉 그 포인터가 가리키고 있는 메모리를 해제시킵니다.

delete 는 힙 메모리를 해제할 때에만 사용할 수 있는데 new 를 통하여 힙 메모리를 할당하고 그 주소를 리턴하면 내부적으로 해당 주소에 얼마만큼의 힙 메모리 크기를 받았었는지를 저장하고 기억해놓습니다. https://stackoverflow.com/questions/197675/how-does-delete-know-the-size-of-the-operand-array 링크에서 이와 같이 말하고 있습니다. "When you allocate memory on the heap, your allocator will keep track of how much memory you have allocated. This is usually stored in a "head" segment just before the memory that you get allocated. That way when it's time to free the memory, the de-allocator knows exactly how much memory to free."

그렇기 때문에 new Derived(5); 를 통해 할당받은 주소만 delete 에 넘겨주면 알아서 이 new Derived(5); 로 할당받은 Dereived 타입의 객체 크기만큼만! 반납을 해주는 것입니다. 내부적으로 해당 주소로 할당 받은 힙 메모리의 '크기'가 얼마였는지를 기억을 하고 있기 때문에 그렇습니다.

때문에 포인터의 타입이 Base 인 것이랑은 관련 없이 어차피 이 포인터 값은 new Derived(5); 로 할당받은 Dereived 타입의 객체의 주소입니다. 이 주소만 넘겨주면 delete 이 알아서 이 객체 힙 메모리를 전부 해제시킵니다. 이 주소로 할당 받았었던 크기를 알고 있으니까요!

결론적으로 delete 는 그 포인터의 타입에 따라 얼마만큼의 크기를 해제할지 알아내고 그에 따라 해제 크기를 결정하는게 아니라, new 때부터 할당한 메모리의 주소엔 얼마만큼의 크기의 메모리를 받았었다는 그 정보를 시스템 내부적으로 기억을 하고 있기 때문에 delete 에 포인터 '값' 을 넘겨주면 그 주소엔 얼마만큼의 할당받은 메모리가 들어있는지 알 수 있기 때문에 값만 넘겨주면 알아서 할당 받았었던 그 크기만큼의 메모리만 딱 해제해주는 식인 것입니다. 

상속은 물려받는다는 개념입니다. 그렇기 떄문에 이 new Derived(5); 객체 메모리 하나 안에는 Base 로부터 물려 받은 멤버 부분도 들어 있고 Derived 만의 멤버 부분도 함께 들어있습니다. 그래서 new Derived(5); 객체를 해제하면 이 객체 메모리엔 Base 로부터 물려받은 부분도 있으므로 이 부분을 해제할 땐 Base 소멸자를 호출하는 과정이 필요합니다. 물론 Dereved 본인만의 것들은 Derived 소멸자 호출이 필요하구요! 

홍재윤님의 프로필

홍재윤

질문자

2021.07.31

궁금증이 명확하게 해결되었습니다 감사합니다