2010-07-22 1 views
1

다음 코드에서는 b, qe의 소멸자가 호출되는 순서는 무엇이며 예외를 처리하기 전에 호출됩니다. 는 (이하 "cout을가 ..."부분은 원래의 질문에 대한 남아 있습니다)예외 매개 변수를 값으로 catch 할 때 소멸자가 호출되는 순서는 무엇입니까?

#include <iostream> 
using namespace std; 

class A { 
public: 
    A(int arg) : m(arg) { 
    cout << "A::A(int) " << m << endl; 
    m = 2*arg; 
    } 
    virtual void f() { 
    cout << "A::f() " << m << endl; 
    } 
    void g() { 
    cout << "A::g(A) " << m << endl; 
    } 

    int m; 
}; 

class B : public A { 
public: 
    B(int arg) : A(arg) { 
    cout << "B::B(int) " << m << endl; 
    m = 3*arg; 
    } 
    ~B() { 
    cout << "B::~B()" << endl; 
    } 
    void f() { 
    cout << "B::f(A&) " << m << endl; 
    } 
    virtual void g() { 
    B q(*this); 
    throw q; 
    cout << "B::g(A) " << m << endl; 
    } 
}; 

int main() { 
    try { 
    B b(1); 
    b.g(); 
    } catch (A e) { 
    cout << "Error: "; 
    e.f(); 
    } 
    return 0; 
} 

이 가능하면 , 당신은 이유를 설명 할 수있다. 감사합니다.

+1

'b'는 절대 삭제되지 않기 때문에 소멸자가 호출되지 않습니다. (즉, 유출되었습니다.) – GManNickG

+0

코드를 정적 할당으로 편집했습니다. 고맙습니다. – hizki

+0

@hizki : 실제로 정적 할당이 아닌 자동 할당 (스택 할당)입니다. – GManNickG

답변

1

q의 desructructor가 스택 unwinding의 첫 번째 부분 (가장 안쪽 범위의 로컬 객체가 먼저 파괴됨)으로 파괴되므로 먼저 호출되고 b의 소멸자가 스택 unwinding의 일부로도 호출됩니다. 모두 catch 블록이 입력되기 전에 두 개가 모두 삭제됩니다. 스택 해제는 예외 핸들러가 실행되기 전에 발생합니다. 염두

베어하지만, 그 예외 객체가 너무 B::g()에 복사 생성 b의 사본이며 수명이 캐치 블록의 단부까지 연장 q 사본 (예외 오브젝트). e을 초기화 (조각화)하는 데 사용됩니다.

예외 개체 자체의 소멸자 (q 복사본)는 이 파괴 된 직후에 실행됩니다 (처리기가 throw;을 통해 종료하지 않음). 이 순서는 표준에 명시되어 있습니다.

관련 문제