2010-02-12 4 views
84

오 C++ 전문가, 나는 지혜를 구합니다. 나에게 standardese을 말하고 다음과 같은 프로그램이 나의 경우 C++ 보장 알려주기 :멤버 생성자 및 소멸자 호출 순서

#include <iostream> 
using namespace std; 

struct A 
{ 
    A() { cout << "A::A" << endl; } 
    ~A() { cout << "A::~" << endl; } 
}; 

struct B 
{ 
    B() { cout << "B::B" << endl; } 
    ~B() { cout << "B::~" << endl; } 
}; 

struct C 
{ 
    C() { cout << "C::C" << endl; } 
    ~C() { cout << "C::~" << endl; } 
}; 

struct Aggregate 
{ 
    A a; 
    B b; 
    C c; 
}; 

int main() 
{ 
    Aggregate a; 
    return 0; 
} 

항상 즉

A::A 
B::B 
C::C 
C::~ 
B::~ 
A::~ 

를 생성합니다, 회원은 선언의 순서에 의해 초기화 및 역으로 파괴 보장됩니다 주문?

+7

클래스가 크고 불투명 해지면 미묘한 버그가 발생하는 합리적 인 원인이됩니다. 50 개의 데이터 멤버가 있고 생성자 초기화 목록에 초기화 된 멤버가 많으면 이니셜 라이저 목록에 순서가 있다고 가정하는 것이 쉽습니다. 결국 코드 작성자는 목록을 신중하게 주문했습니다 ... 그렇지 않습니까? – Permaquid

답변

104

다른 말로하면 멤버는 선언 순서에 따라 초기화되고 역순으로 소멸됩니다.

모두에 예 참조 12.6.2

6 초기화 순서 다음 진행한다 가상베이스 후술

  • 첫째 단 가장 유래 클래스의 생성자 클래스는 순서로 초기화되어야합니다. 방향성 비선형 그래프의 왼쪽에서 오른쪽 순회 순으로 나타납니다. 0 클래스를 사용합니다. 여기서 "왼쪽에서 오른쪽으로"는 기본 클래스 의 모양이 인 순서입니다. 기본 지정자 목록. 그들은 ( 없이 마이크로 전자 기계 - 초기화 순서의) 상기베이스 지정자리스트 표시로

  • 후, 직접 베이스 클래스 선언 순서를 초기화한다.

  • 이어서, 비 - 정적 데이터 멤버 (다시 상관없이 MEM-초기화의 순서)가 클래스 정의 선언 된 순서 초기화한다.

  • 마지막으로 본체의 복합 문인 이 실행됩니다. [참고 : 선언 순서는 에 기본 및 구성원 하위 개체 이 초기화의 역순으로 파괴되도록합니다. 예, 표준 보장 개체가 생성 된 역순으로 파괴 얻을

+0

내가 올바르게 기억한다면, 둘 다 예 ... 스택으로 생각하십시오. 먼저 푸시되고, 마지막으로 팝업됩니다. 따라서 첫 번째 인스턴스를 인스턴스화하면 스택 순서대로 메모리에 푸시됩니다. 그런 다음 두 번째가 밀려 나오고 세 번째는 두 번째로 밀려납니다. 그런 다음, 당신의 인스턴스를 파괴 할 때, 프로그램은 제일 먼저 파괴 된 것을 찾아야 만합니다. 하지만이 방법으로 잘못 설명했을 수도 있지만 C/C++ 및 ASM을 수행 할 때 배운 방법입니다. –

5

예와 예. 파괴의 순서는 구성원 변수의 경우 항상 순서와 반대입니다.

26

예 (정적 멤버는 아닙니다). 초기화 (시공)는 12.6.2/5, 파괴는 12.4/6을 참조하십시오.

+2

+1은 _non-static_ 멤버를위한 것임을 나타냅니다. :-) –

7

-end 참고]. 그 이유는 한 물체가 다른 물체를 사용할 수 있기 때문입니다.고려 : b 다음 b 잘못된 멤버 참조를 개최 것 전에 소멸했다

struct A { }; 

struct B { 
A &a; 
B(A& a) : a(a) { } 
}; 

int main() { 
    A a; 
    B b(a); 
} 

a합니다. 객체가 역순으로 파괴되면 올바른 파괴가 보장됩니다.