2010-11-27 2 views
4

Base 클래스에 가상 소멸자 (예 : vtable 항목을 피하기 위해)가없고 Derived 클래스에 기본 속성 만 있으면 기본 클래스의 포인터가 true 인 경우 new로 할당 된 모든 메모리가 해제됩니다. 삭제 되었습니까? 파생 클래스의 소멸자가 호출되지 않을 것이지만 전체 객체에 의해 할당 된 메모리가 해제되는지 궁금합니다. Derived 포인터에서 delete를 호출하면 전체 메모리 공간을 비울 것이라고 가정합니다. 이 메모리의 파생 클래스 부분을 해제하지 않을 경우비 - 가상 소멸자 및 기본 클래스 포인터를 사용하여 전체 개체를 해제 할 수 있습니까?

또한, 어떻게을 무료로 얼마나 많은 메모리를 알고, 기본 클래스에 가상 소멸자의 같은 경우에 있지만 함께 작동합니까?

Exemple :

class Base { 
    public: 
    int a; 
    int b; 
    Base() {} 
    ~Base() {} 
}; 

class Derived : public Base { 
    public: 
    int c; 
    int d; 
    Derived() {} 
    ~Derived() {} 
}; 

int main() { 
    Base *p = new Derived(); 
    delete p; // is memory allocated for Derived freed? 
    return 0; 
} 

답변

4

그것은 정의되지 않은 동작, 그래서 아무것도 발생할 수 있습니다. 표준 [expr.] 삭제 :

를 첫번째 대안 (개체를 삭제) 삭제 대상물 의 정적 유형이 동적 유형과 다른 경우, 정적 유형 동적 유형의 기본 클래스이어야한다 의 삭제할 개체와 정적 유형은 가상의 소멸자를 가져야하며, 동작은 입니다.

일반적인 구현 방법은 구현 세부 사항이지만 파생 클래스의 소멸자를 자동으로 재정의하고 거기에서 메모리 릴리스를 구현할 수 있습니다. 구현시 가상 테이블에 항목을 예약 할 수 있도록 기본 클래스에 가상 소멸자를 정의해야합니다.

0

편집 : 표준 초안의 주요 산문, 강조 광산 : 내가 잘못 되었습니까 5.3.5 절

3 첫 번째 대안은 ( 개체를 삭제)하는 경우 삭제 될 객체의 정적 유형이 동적 유형과 다르다면, 정적 유형 은 동적 유형 유형의 삭제할 객체 유형이어야하고 정적 유형 은 가상의 소멸자를 가져야하며, 동작은 입니다. (배열 삭제) 동적 유형이 인 경우 삭제할 개체가 정적 유형과 다르면 동작이 으로 정의되지 않습니다.

+3

올바르지 않습니다. 삭제 연산자는 주어진 유형에 따라 작동합니다. 이 경우'Base '를 삭제하려고 시도합니다. –

+1

누락 된 부분은 가상 소멸자가 없기 때문에 정의되지 않은 동작이 발생합니다. –

+1

강조된 문구 : 가상 소멸자가 있거나 동작이 정의되지 않았습니다. – SingleNegationElimination

3

공식적으로 말하자면 이것은 정의되지 않은 동작이므로 메모리가 해제되거나 실제로 프로그램에서 아무 것도 수행하지 않는다고 보장 할 수 없습니다. 하드 디스크를 포맷 할 수 있습니다. 그렇지 않을 수도 있습니다. 실제로 메모리는이 경우에는 해제 될 수 있습니다. 그러나 메모리를 사용하면 안심할 수 있습니다. 그것만큼이나 간단합니다.

+0

-1, 왜 저를 downvoted 누구? 그냥 궁금해서. –

+1

실제로 파생 된 객체의 파생 된 부분이 보유한 메모리가 해제된다는 것은 의문의 여지가 있습니다. –

+0

그것에 대해 생각해 보면, 아마 맞을 것입니다. 편집 할 것입니다. –

3

기술적으로 대답은 '알 수 없음'입니다. 가상 소멸자가없는 기본 포인터를 파생시킬 포인터를 삭제하면 정의되지 않은 동작이 발생합니다.

그러나 실제로 구현 된 대부분의 구현에서는 파생 된 객체의 내용을 올바르게 삭제하지 못합니다.

+0

틀렸어. – mjfgates

+1

아니요, 저는 아닙니다 ... –

+4

+ 1 - 실제로, 그는 아닙니다. –

-4

매우 특정한 경우에는 파생 클래스 개체에서 사용하는 모든 메모리가 가상 소멸자가 없을 때 해제됩니다. (비 가상 소멸자를 사용하는 경우 항상 내가 언어를 사용하는 클래스에서 상속 허용 것이라고 생각하지 않습니다, 메모리 누수가 파생 클래스 일으켰!)

가 기억 소멸자는 메모리를 해제 것이 아니다; "삭제"는 메모리를 해제합니다. 소멸자는 삭제로 CALLED되는 함수입니다. 등 등 등 그주의 미래 저쩌구에

ㅋ ㅋ ㅋ ㅋ ㅋ ㅋ 확장 ㅋ ㅋ ㅋ ㅋ 직접 원인이 문제는 당신은 분명 무슨 말인지 알고있다.

+1

불행히도 이것은 올바르지 않습니다. 언어는 기본 클래스에 대한 포인터를 통해 반드시 삭제하지 않을 수도 있기 때문에 가상 소멸자가없는 클래스에서 상속을 허용합니다. 그렇게하면 정의되지 않은 것입니다. –

+3

하지만 당신은 사실 잘못입니다. –

+0

오케이, 현실 확인. VC++ 2008을 실행하고 위의 코드를 복사하여 붙여 넣은 다음 main()의 할당 및 삭제 주위에 while (1) 루프를 넣고 GO를 누릅니다. CPU 사용량이 50-75 % 사이에서 튀어 오르고 있으므로 수십억의 할당이 이루어지고 있으며 메모리 사용량은 1.76GB로 평 균합니다. Visual C++ 2008에서는 기본 포인터를 통해 파생 클래스를 해제하면 모든 메모리가 비어집니다. – mjfgates

0

메모리를 올바르게 해제 할 가능성이 있습니다. 표준이 이것을 보장하지 않는다고해서 그것이 작동하지 않는다는 것을 의미하지는 않습니다. 어떻게 실패 할지를 알기가 어렵습니다.

+0

사소한 일 : 컴파일러는'_Internal_free (p, sizeof (Base)) '를 포함하여 모든 것을 인라인 할 것이다. – MSalters

관련 문제