33

고려 :함수가 생성자의 이니셜 라이저 목록에서 시퀀스를 호출합니까?

int f() { 
    static int i = 0; 
    return i++; 
} 

struct Test { 
    int a, b; 
    Test() : a(f()), b(f()) {} 
}; 

Test t; 

나는 a 인해 struct에서의 선언의 순서에 b 전에 초기화되는 것을 알고있다.

g(f(), f())에있는 f에 대한 두 번의 호출은 순서가 지정되지 않았습니다.

그럼 t.a == 0t.b == 1이 보장되는지 궁금합니다.

+0

@ FrançoisAndrieux 나는 그것이 중복이라고 생각하지 않습니다. 이 질문은 특히 회원 초기화 목록에서 함수 호출의 순서를 다루고 있습니다.이 목록은 해당 질문이 다루지 않는 것입니다. – Xirema

+0

@ FrançoisAndrieux - 그것은 멍청이라고 생각하지 마십시오. OP는'a'가'b' 전에 초기화된다는 것을 압니다. 그러나'f()'에 대한 두 번의 호출이 순서인지 아닌지 묻습니다. 'a' 나'b'가 초기화되기 전에'f()'가 두 번 호출 될 수 있습니다. –

+1

확인이 필요하지만 믿을 수 있습니다. –

답변

30

따라서 t.a == 0t.b == 1이 보장되는지 궁금합니다. a 클래스 선언에 b 전에 와서 아무것도 다른 ab의 초기화 사이 f() 호출하지 않기 때문에

항상 너무 오래 사실 것입니다. 클래스 멤버는 클래스에서 선언 된 순서대로 초기화됩니다. [class.base.init]/11 : 비 위임 생성자에서

, 다음 순서로 초기화 진행 [...]

  • 이어서, 비 - 정적 데이터 멤버는 초기화 클래스 정의에서 선언 된 순서대로 (다시 mem-initializers의 순서와 관계없이). 생성자가 a를 초기화 한 후 때 ab 앞에 오는 이후

그래서 처음 f()를 호출하고 b을 초기화 할 때 그것은 두 번째를 호출합니다.

우리는 또한 알고 부재 사이 이니셜 시퀀스 점 때문에 [class.base.init]/7

... 각각 MEM-초기화가 수행하는 초기화를 구성하는 전체 표현식 . mem-initializer의 모든 표현식은 초기화를 수행하는 전체 표현식의 일부로 평가됩니다. [intro.execution]/14

전체 발현과 관련된 모든 값이 계산 및 부작용 전에 모든 서열화된다

각 이니셜 전체 표현하고 각 풀 식 서열화 말해 준다 값 계산 및 평가 될 다음 전체 표현식과 연관된 부작용이 있습니다.

+0

화려한 대답! 하지만 물론'f()'만이 다른 어디에도 호출되지 않고, 특히 다른 정적 이니셜 라이저가 없다면 : – Christophe

+0

@Christophe Thanks. 나는 그 작은 맛있는 음식을 더했다. – NathanOliver

6

구조체에서의 선언 순서 때문에 b가 초기화되기 전에 a가 초기화된다는 것을 알고 있습니다.

사실입니다.

b이 초기화되기 전에 이니셜 라이저 표현식의 평가가 완료되지 않는 한은 내게 b 전에 a을 초기화 할 수 없습니다.

정적이 아닌 멤버를 초기화하는 데 사용되는 식의 평가 순서를 지정하는 표준이 없습니다. 그러나 C++ 11 표준 (12.6.2/12)에서 다음 예제를 볼 수 있습니다.

mem-initializer의 expression-list 또는 braced-init-list에있는 이름은 범위에서 평가됩니다 mem-initializer가 지정된 생성자의 이름. [예 : i 초기화 후 this->i 평가 시퀀싱되지 않는다면 유효하지 않을 것이다

class X { 
    int a; 
    int b; 
    int i; 
    int j; 
    public: 
    const int& r; 
    X(int i): r(a), b(i), i(i), j(this->i) { } 
}; 

.