2009-11-21 7 views
8

다음 코드 조각에서 d1의 초기화 프로그램이 아직 구성되지 않은 d2를 전달 (올바른?)하므로 D의 복사 생성자에서 d.j가 초기화되지 않은 메모리 액세스입니까?표준에 따라 초기화 순서가 보장됩니까?

struct D 
{ 
    int j; 

    D(const D& d) { j = d.j; } 
    D(int i) { j = i; } 
}; 

struct A 
{ 
    D d1, d2; 
    A() : d2(2), d1(d2) {} 
}; 

데이터 멤버의 초기화 순서에 대해 설명하는 섹션은 무엇입니까?

+0

관련이 있지만 중복되지 않음 질문 : http://stackoverflow.com/questions/1589950/initializer-list-argument-evaluation-order –

답변

11

지금 표준을 사용하지 않아서 섹션을 인용 할 수 없지만 구조 또는 클래스 멤버 초기화 항상은 선언 된 순서대로 발생합니다. 생성자 이니셜 라이저 목록에서 멤버가 언급되는 순서는 적합하지 않습니다.

 
     -Wreorder (C++ only) 
      Warn when the order of member initializers given in the code does 
      not match the order in which they must be executed. For instance: 

        struct A { 
        int i; 
        int j; 
        A(): j (0), i (1) { } 
        }; 

      The compiler will rearrange the member initializers for i and j to 
      match the declaration order of the members, emitting a warning to 
      that effect. This warning is enabled by -Wall. 
+5

이유는 사물이 생성 된 역순으로 파괴된다는 것입니다. 순서 멤버가 소멸자 다음에 소멸되도록 변경할 수 없으므로 생성 된 순서는 반드시 일치해야합니다. – GManNickG

+2

그러나 여기에서 설명한대로 이전에 초기화 된 멤버를 참조 할 수도 있습니다. http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.7 – Jherico

+1

이 경우의 FAQ 설명은 매우 유용합니다. 나는 생각한다. 표준은 "각 기지와 회원의 초기화 후 순차 지점이있다"고 말한다 (12.6.2/3). –

1

예 :

GCC는 순서가 다른 경우 경고하는 경고 -Wreorder 있습니다. 좋은 컴파일러는 A::d2A::d1 이후에 초기화된다는 경고를해야합니다. 하여 예에서

6

는 실패한다 : 결과

struct A 
{ 
    D d1, d2;  
    A() : d2(2), d1(d2) {} 
}; 

d1: is initialised first as it is declared first. 
d2: is then initialized. 

이니셜리스트 유효 물체 (D2)를 참조하여 (D1)를 구성한다.

이것은 컴파일러의 경고 수준을 최대한 높일 수있는 한 가지 이유입니다.
또한 모든 경고를 오류로보고하도록 강제합니다.

2

이 현상은 Meyer 's Effective C++의 항목 13에서 설명되었거나 강조 표시되었습니다. 소멸자는 생성자의 역순으로 요소를 파괴해야하므로 모든 생성자는 동일한 순서로 요소를 초기화해야하므로 초기화 목록의 시퀀스 대신 선언 된 순서로 초기화해야합니다. .

11

C++ 표준 (ISO/IEC 14882 : 2003 12.6.2/5, 초기화 기지와 회원) 말한다 :

초기화는 다음과 같은 순서로 진행된다

:

- 첫째, 아래에 설명 된 것처럼 가장 많이 파생 된 클래스의 생성자에 대해서만 가상 기본 클래스는 기본 클래스의 지시 된 비순환 그래프의 깊이 우선 왼쪽에서 오른쪽 탐색에서 나타나는 순서대로 초기화되어야합니다. 여기서 "왼쪽에서 다음으로 -right "는 파생 된 기본 클래스 이름의 출현 순서입니다. 클래스 기본 지정 r-list.

- 직접 기본 클래스는 (mem-initializers의 순서와 관계없이) base-specifier-list에 나타나는 것처럼 선언 순서로 초기화되어야합니다.

- 비 정적 데이터 멤버는 클래스 정의에서 선언 된 순서대로 초기화됩니다 (다시 mem-initializer의 순서와 관계 없음).

- 마지막으로 생성자의 본문이 실행됩니다.

글 머리 기호 3은 비 정적 데이터 멤버 초기화 순서를 보장합니다.

관련 문제